gemercheung 9 ay önce
ebeveyn
işleme
e6fd039027

+ 16 - 11
src/util/gl.ts

@@ -235,22 +235,22 @@ export const createFPSCamera = (
 
   const start = vec2.create();
   const mousedownHandler = (ev: MouseEvent) => {
-    start[0] = ev.offsetX;
-    start[1] = ev.offsetY;
+    start[0] = ev.clientX;
+    start[1] = ev.clientY;
 
-    mount.addEventListener("mousemove", mouseMoveHandler);
-    mount.addEventListener("mouseup", mouseUpHandler);
+    document.documentElement.addEventListener("mousemove", mouseMoveHandler);
+    document.documentElement.addEventListener("mouseup", mouseUpHandler);
   };
 
   const rotatePixelAmount = 1500;
   const mouseMoveHandler = (ev: MouseEvent) => {
-    const end = vec2.fromValues(ev.offsetX, ev.offsetY);
+    const end = vec2.fromValues(ev.clientX, ev.clientY);
     const move = vec2.sub(vec2.create(), end, start);
     pitch += (move[1] / rotatePixelAmount) * Math.PI;
-    if (pitch > 89) {
-      pitch = 89;
-    } else if (pitch < -89) {
-      pitch = -89;
+    if (pitch > Math.PI / 2) {
+      pitch = Math.PI / 2;
+    } else if (pitch < -Math.PI / 2) {
+      pitch = -Math.PI / 2;
     }
     yaw -= (move[0] / rotatePixelAmount) * Math.PI;
     start[0] = end[0];
@@ -260,8 +260,8 @@ export const createFPSCamera = (
   };
 
   const mouseUpHandler = () => {
-    mount.removeEventListener("mousemove", mouseMoveHandler);
-    mount.removeEventListener("moseup", mouseUpHandler);
+    document.documentElement.removeEventListener("mousemove", mouseMoveHandler);
+    document.documentElement.removeEventListener("moseup", mouseUpHandler);
   };
   const wheelHandler = (ev: WheelEvent) => {
     const amount = ev.deltaY * -0.01;
@@ -290,6 +290,11 @@ export const createFPSCamera = (
       updateFront();
       updateCameraMat();
     },
+    setYaw(_yaw: number) {
+      yaw = _yaw
+      updateFront();
+      updateCameraMat();
+    },
     destory: mergeFuns(mouseUpHandler, () =>
       document.removeEventListener("wheel", wheelHandler)
     ),

+ 1 - 1
src/view/map/install.ts

@@ -16,7 +16,7 @@ mapManage.setCenter(defaultCenter);
 watchEffect(() => mapManage.setTileType(tileType.value));
 
 export const noValidPoint = (pos: ScenePoint) =>
-  !pos.pos || pos.pos.length === 0 || pos.pos.some((i) => !i);
+  !pos?.pos || pos.pos.length === 0 || pos.pos.some((i) => !i);
 export const validScene = (scene: Scene) => !scene.scenePos.every(noValidPoint);
 
 export const flyScene = (scene: Scene) => {

+ 13 - 3
src/view/map/pc4Helper.ts

@@ -75,10 +75,20 @@ export const exportImage = async (points: ScenePoint[], name?: string) => {
   const downloadImages = Promise.all(
     points.map((point) => {
       const url = getPointPano(point) as string;
+
+
       let loadBlob: Promise<Blob>
-      if (noValidPoint(point.pos as any)) {
-        const ration = 6;
-        loadBlob = addWatermark(url, point!.pos, ration)
+      console.log(point.pos, noValidPoint(point.pos as any))
+      if (!noValidPoint(point)) {
+        let ration = 6;
+        loadBlob = new Promise<void>(resolve => {
+          const img = new Image()
+          img.src = url
+          img.onload = () => {
+            ration = img.width / 2730
+            resolve()
+          }
+        }).then(() => addWatermark(url, point!.pos, ration))
       } else {
         loadBlob = fetch(url).then(res => res.blob())
       }

+ 7 - 3
src/view/pano/env.ts

@@ -79,7 +79,7 @@ const getDrawVaring = (gl: WebGL2RenderingContext) => {
   };
 };
 
-export const init = (canvas: HTMLCanvasElement) => {
+export const init = (canvas: HTMLCanvasElement, initYaw: number) => {
   let activeTex: "skyCubeTex1" | "skyCubeTex" = "skyCubeTex1";
   const gl = canvas.getContext("webgl2", { preserveDrawingBuffer: true })!;
   const program = createProgram(gl, envVertSource, envFragSource);
@@ -126,7 +126,7 @@ export const init = (canvas: HTMLCanvasElement) => {
 
   setSize([canvas.width, canvas.height]);
   const fps = createFPSCamera(
-    canvas.parentElement!,
+    canvas!,
     (nViewMat) => {
       mat4.copy(viewMat, nViewMat);
       updateInv();
@@ -134,12 +134,16 @@ export const init = (canvas: HTMLCanvasElement) => {
     },
     [0, 1, 0],
     [0, 0, 0],
-    { yaw: glMatrix.toRadian(0) },
+    { yaw: glMatrix.toRadian(initYaw) },
     80
   );
   return {
     setSize,
     redraw,
+    setYaw(yaw: number) {
+      fps.setYaw(yaw)
+      redraw()
+    },
     changeUrls(urls: string | string[]) {
       fps.recovery();
       return varing.preset(urls).then(() => {

+ 24 - 65
src/view/pano/pano.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="pano-layout" v-loading="loading">
+  <div class="pano-layout" v-loading="loading" :element-loading-text="loadingStr">
     <canvas ref="panoDomRef"></canvas>
     <div class="btns">
       <el-button
@@ -10,6 +10,14 @@
       >
         屏幕拍照
       </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"
@@ -42,7 +50,8 @@
 import SingleInput from "@/components/point-input.vue";
 import { router, setDocTitle } from "@/router";
 import { mergeFuns, round } from "@/util";
-import { computed, onMounted, onUnmounted, ref, watchEffect } from "vue";
+import { glMatrix } from "gl-matrix";
+import { computed, nextTick, onMounted, onUnmounted, ref, watchEffect } from "vue";
 import { init } from "./env";
 import {
   updateScenePointName,
@@ -56,12 +65,15 @@ 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);
@@ -85,6 +97,7 @@ const panoUrls = computed(() => {
 });
 const update = ref(false);
 const loading = ref(false);
+const loadingStr = ref("");
 
 const getGis = () => {
   const pos = point.value!.pos as number[];
@@ -99,73 +112,16 @@ const copyGis = async () => {
   ElMessage.success("经纬度高程复制成功");
 };
 
-const canvas = document.createElement("canvas");
-// 水印添加函数
-const addWatermark = (imgURL: string, ration: number) => {
-  const ctx = canvas.getContext("2d");
-  const image = new Image();
-  image.src = imgURL;
-
-  return new Promise<string>((resolve, reject) => {
-    image.onload = () => {
-      canvas.width = image.width;
-      canvas.height = image.height;
-      ctx.drawImage(image, 0, 0, image.width, image.height);
-
-      const font = `${ration * 20}px Arial`;
-      const pos = point.value!.pos as number[];
-      const lines = `经度: ${toDegrees(pos[0])}\n纬度: ${toDegrees(pos[1])}`.split("\n");
-      const lineTopPadding = 5 * ration;
-      const lineBounds = lines.map((line) =>
-        getTextBound(line, font, [lineTopPadding, 0])
-      );
-      const bound = lineBounds.reduce(
-        (t, { width, height }) => {
-          t.width = Math.max(t.width, width);
-          t.height += height;
-          return t;
-        },
-        { width: 0, height: 0 }
-      );
-      const padding = 20 * ration;
-      const margin = 80 * ration;
-
-      const position = [
-        image.width - margin - bound.width,
-        image.height - margin - bound.height,
-      ];
-
-      ctx.rect(
-        position[0] - padding,
-        position[1] - padding,
-        bound.width + 2 * padding,
-        bound.height + 2 * padding
-      );
-      ctx.fillStyle = "rgba(0, 0, 0, 0.3)";
-      ctx.fill();
-
-      ctx.font = font;
-      ctx.textBaseline = "top";
-      ctx.fillStyle = "#fff";
-      let itemTop = 0;
-      lines.forEach((line, ndx) => {
-        ctx.fillText(line, position[0], position[1] + itemTop + lineTopPadding);
-        itemTop += lineBounds[ndx].height;
-      });
-      resolve(canvas.toDataURL("image/jpeg", 1));
-    };
-    image.onerror = reject;
-  });
-};
-
 const photo = async () => {
   loading.value = true;
+  loadingStr.value = "原图提取中";
   await new Promise((resolve) => setTimeout(resolve, 300));
-  const ration = 3;
+  const ration = tempRadion.value;
+  console.log("ration", ration);
   setSize(ration, 1920, 1080);
-  let dataURL = panoDomRef.value.toDataURL("image/jpeg", 1);
+  let dataURL: Blob | string = panoDomRef.value.toDataURL("image/jpeg", 1);
   if (!noValidPoint(point.value)) {
-    dataURL = await addWatermark(dataURL, ration);
+    dataURL = await addWatermark(dataURL, point.value!.pos, ration);
   }
 
   await saveAs(dataURL, `${relics.value?.name}.jpg`);
@@ -184,7 +140,7 @@ const setSize = (ration: number, w?: number, h?: number) => {
 
 onMounted(() => {
   if (!panoDomRef.value) throw "没有canvas DOM";
-  pano = init(panoDomRef.value);
+  pano = init(panoDomRef.value, 0);
   const resizeHandler = () => {
     setSize(devicePixelRatio);
   };
@@ -196,6 +152,9 @@ onMounted(() => {
       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,