123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- <template>
- <div class="pano-layout" v-loading="loading" :element-loading-text="loadingStr">
- <canvas ref="panoDomRef"></canvas>
- <div class="btns">
- <el-button
- size="large"
- type="primary"
- style="margin-right: 20px; width: 100px"
- @click="photo"
- >
- 屏幕拍照
- </el-button>
- <!-- <el-input-number
- style="margin-right: 20px"
- v-model="tempRadion"
- :precision="2"
- :step="0.01"
- :min="1"
- :max="3"
- /> -->
- <el-button
- size="large"
- style="margin-right: 20px; width: 100px"
- @click="copyGis"
- v-if="point && !noValidPoint(point)"
- >
- 复制经纬度
- </el-button>
- <el-button
- size="large"
- type="primary"
- style="width: 100px"
- @click="update = true"
- v-if="router.currentRoute.value.name === 'pano'"
- >
- 测点说明
- </el-button>
- </div>
- </div>
- <SingleInput
- v-if="point"
- :visible="update"
- @update:visible="update = false"
- :value="point"
- :update-value="(npoint) => updateScenePointName(npoint)"
- />
- </template>
- <script setup lang="ts">
- import SingleInput from "@/components/point-input.vue";
- import { router, setDocTitle } from "@/router";
- import { mergeFuns, round } from "@/util";
- import { glMatrix } from "gl-matrix";
- import { computed, nextTick, onMounted, onUnmounted, ref, watchEffect } from "vue";
- import { init } from "./env";
- import {
- updateScenePointName,
- getPointPano,
- ScenePoint,
- scenePoints,
- } from "@/store/scene";
- import { copyText, toDegrees, getTextBound } from "@/util";
- import { ElMessage } from "element-plus";
- import saveAs from "@/util/file-serve";
- import { DeviceType } from "@/store/device";
- import { initRelics, relics } from "@/store/relics";
- import { noValidPoint } from "../map/install";
- import { addWatermark } from "@/util/image";
- type Params = { pid?: string; relicsId?: string } | null;
- const params = computed(() => router.currentRoute.value.params as Params);
- const panoDomRef = ref<HTMLCanvasElement>();
- const destroyFns: (() => void)[] = [];
- const point = ref<ScenePoint>();
- const tempRadion = ref(3.0);
- watchEffect(() => {
- if (params.value?.pid) {
- const pid = Number(params.value!.pid);
- point.value = scenePoints.value.find((scene) => scene.id === pid);
- if (!point.value) {
- initRelics(Number(params.value.relicsId)).then(() => {
- point.value = scenePoints.value.find((scene) => scene.id === pid);
- if (!point.value) {
- router.replace({ name: "relics" });
- }
- });
- }
- }
- });
- const panoUrls = computed(() => {
- return (
- point.value && getPointPano(point.value, point.value.cameraType === DeviceType.CLUNT)
- );
- });
- const update = ref(false);
- const loading = ref(false);
- const loadingStr = ref("");
- const getGis = () => {
- const pos = point.value!.pos as number[];
- return `经度: ${toDegrees(pos[0])}\n纬度: ${toDegrees(pos[1])}\n高程: ${round(
- pos[2],
- 4
- )}`;
- };
- const copyGis = async () => {
- await copyText(getGis());
- ElMessage.success("经纬度高程复制成功");
- };
- const photo = async () => {
- loading.value = true;
- loadingStr.value = "原图提取中";
- await new Promise((resolve) => setTimeout(resolve, 300));
- const ration = tempRadion.value;
- console.log("ration", ration);
- setSize(ration, 1920, 1080);
- let dataURL: Blob | string = panoDomRef.value.toDataURL("image/jpeg", 1);
- if (!noValidPoint(point.value)) {
- dataURL = await addWatermark(dataURL, point.value!.pos, ration);
- }
- await saveAs(dataURL, `${relics.value?.name}.jpg`);
- ElMessage.success("图片导出成功");
- setSize(devicePixelRatio);
- loading.value = false;
- };
- let pano: ReturnType<typeof init>;
- const setSize = (ration: number, w?: number, h?: number) => {
- const canvas = panoDomRef.value!;
- canvas.width = (w || canvas.offsetWidth) * ration;
- canvas.height = (h || canvas.offsetHeight) * ration;
- pano.setSize([canvas.width, canvas.height]);
- };
- onMounted(() => {
- if (!panoDomRef.value) throw "没有canvas DOM";
- pano = init(panoDomRef.value, 0);
- const resizeHandler = () => {
- setSize(devicePixelRatio);
- };
- resizeHandler();
- window.addEventListener("resize", resizeHandler);
- destroyFns.push(
- watchEffect(() => {
- if (panoUrls.value) {
- loading.value = true;
- pano.changeUrls(panoUrls.value).then(() => (loading.value = false));
- pano.setYaw(
- point.value.cameraType === DeviceType.CLUNT ? glMatrix.toRadian(180) : 0
- );
- }
- }),
- pano.destory,
- () => {
- window.removeEventListener("resize", resizeHandler);
- }
- );
- });
- onUnmounted(() => mergeFuns(...destroyFns)());
- watchEffect(() => {
- if (router.currentRoute.value.name.toString().includes("pano") && point.value) {
- setDocTitle(point.value.index.toString() || relics.value.name);
- }
- });
- </script>
- <style scoped lang="scss">
- .pano-layout,
- canvas {
- width: 100%;
- height: 100%;
- }
- .pano-layout {
- position: relative;
- .btns {
- position: absolute;
- left: 50%;
- transform: translateX(-50%);
- bottom: 40px;
- z-index: 1;
- }
- }
- </style>
|