Browse Source

添加绘制方法

bill 2 years ago
parent
commit
dd9fb7988a

File diff suppressed because it is too large
+ 1 - 1
server/test/SS-t-P1d6CwREny2/attach/sceneStore


+ 14 - 0
src/graphic/CanvasStyle/default.js

@@ -16,6 +16,18 @@ const Lane = {
   dash: [8, 8],
 };
 
+const Arrow = {
+  lineWidth: 2,
+  strokeStyle: "red",
+}
+
+const Magnifier = {
+  strokeStyle: "#000",
+  lineWidth: 1,
+  fillStyle: "rgba(0,0,0,0)",
+  radius: 10,
+}
+
 const CurveRoad = {
   ...Road,
   lineWidth: 1,
@@ -147,10 +159,12 @@ export default {
   ControlPoint,
   CurveRoadPoint,
   GuideLine,
+  Magnifier,
   Font: CanvasFont,
   MeasureLine,
   Measure,
   Element,
   RoadPoint,
+  Arrow,
   bgColor: "#fff",
 };

+ 4 - 4
src/graphic/Geometry/Magnifier.js

@@ -16,12 +16,12 @@ export default class Magnifier extends Geometry {
     this.setId(vectorId);
   }
 
-  setPosition(position) {
-    if (!position) {
+  setPosition(positionRaw) {
+    if (!positionRaw) {
       return;
     }
-    this.position.x = position.x;
-    this.position.y = position.y;
+    this.position.x = positionRaw.x;
+    this.position.y = positionRaw.y;
     let position = coordinate.getScreenXY(this.position);
     let center = {
       x: coordinate.width / 2,

+ 94 - 10
src/graphic/Renderer/Draw.js

@@ -166,7 +166,7 @@ export default class Draw {
       const endReal = isTemp
         ? vector.end
         : dataService.getRoadPoint(vector.endId);
-      this.drawText(
+      this.drawTextByInfo(
         { x: (startReal.x + endReal.x) / 2, y: (startReal.y + endReal.y) / 2 },
         vector.vectorId
       );
@@ -218,7 +218,7 @@ export default class Draw {
         ctx.lineTo(point2.x, point2.y);
         ctx.stroke();
       }
-      this.drawText(
+      this.drawTextByInfo(
         {
           x: (edgeVector.start.x + edgeVector.end.x) / 2,
           y: (edgeVector.start.y + edgeVector.end.y) / 2,
@@ -356,18 +356,90 @@ export default class Draw {
     this.drawPoint(vector);
   }
 
+  drawArrow(vector) {
+    let start = dataService.getPoint(vector.startId);
+    start = coordinate.getScreenXY(start);
+    let end = dataService.getPoint(vector.endId);
+    end = coordinate.getScreenXY(end);
+    const ctx = this.context
+
+    const ange = 30
+    const L = 8;
+    let a = Math.atan2((end.y - start.y), (end.x - start.x));
+    let xC = end.x - L * Math.cos(a + ange * Math.PI/180); // θ=30
+    let yC = end.y - L * Math.sin(a + ange * Math.PI/180);
+    let xD = end.x - L * Math.cos(a - ange * Math.PI/180);
+    let yD = end.y - L * Math.sin(a - ange * Math.PI/180);
+    ctx.save()
+
+    help.setVectorStyle(
+      this.context,
+      vector,
+      vector.category || vector.geoType
+    );
+    if (vector.arrowColor) {
+      ctx.strokeStyle = vector.arrowColor
+    }
+    ctx.beginPath();
+    ctx.moveTo(start.x, start.y);
+    ctx.lineTo(end.x, end.y);
+    ctx.moveTo(xC, yC);
+    ctx.lineTo(end.x, end.y);
+    ctx.lineTo(xD, yD);
+    ctx.stroke();
+    ctx.restore();
+  }
+
+  drawMagnifier(vector) {
+    const ctx = this.context
+    this.drawPoint({
+      ...vector.position,
+      radius: Style.Magnifier.radius,
+      geoType: vector.geoType,
+    })
+    const pt = vector.position
+    const target = vector.popPosition
+    const style = help.setVectorStyle(ctx, vector)
+    const offset = style.radius / 2
+    console.log(pt, target, pt, style.radius)
+    const targetPts = [
+      mathUtil.translate(pt, target, pt, style.radius),
+      target
+    ]
+
+    ctx.save();
+    ctx.beginPath()
+    ctx.moveTo(pt.x - offset, pt.y)
+    ctx.lineTo(pt.x + offset, pt.y)
+    ctx.stroke();
+    ctx.beginPath()
+    ctx.moveTo(pt.x, pt.y - offset)
+    ctx.lineTo(pt.x, pt.y + offset)
+    ctx.stroke();
+    if (targetPts) {
+      ctx.beginPath()
+      ctx.moveTo(targetPts[0].x, targetPts[0].y)
+      ctx.lineTo(targetPts[1].x, targetPts[1].y)
+      ctx.stroke();
+    }
+    ctx.restore();
+  }
+
   drawCircle(element) {
     this.drawPoint({
+      ...element,
       ...element.center,
-      radius: element.radius,
-      geoType: element.geoType,
     });
   }
 
   drawPoint(vector) {
-    const pt = coordinate.getScreenXY({ x: vector.x, y: vector.y });
+    // const pt = coordinate.getScreenXY({ x: vector.x, y: vector.y });
+    const pt = vector
     const ctx = this.context;
     const style = help.setVectorStyle(ctx, vector, vector.geoType || "Point");
+    if (vector.color) {
+      ctx.strokeStyle = vector.color
+    }
     const radius = (vector.radius || style.radius) * coordinate.ratio;
     ctx.save();
     ctx.beginPath();
@@ -378,18 +450,20 @@ export default class Draw {
 
     if (import.meta.env.DEV) {
       if (vector.vectorId) {
-        this.drawText(vector, vector.vectorId);
+        this.drawTextByInfo(vector, vector.vectorId);
       }
     }
   }
 
-  // 文字
-  drawText(position, txt, angle) {
+  drawTextByInfo(position, txt, angle, setStyle = true) {
     const ctx = this.context;
     ctx.save();
-    help.setVectorStyle(ctx, null, "Text");
+    setStyle && help.setVectorStyle(ctx, null, "Text");
 
     const pt = coordinate.getScreenXY(position);
+    const text = ctx.measureText("foo");
+    pt.x -= text.width / 2
+    pt.y -= (text.actualBoundingBoxAscent + text.actualBoundingBoxDescent) / 2
     if (angle) {
       ctx.translate(pt.x, pt.y);
       ctx.rotate(angle);
@@ -400,7 +474,18 @@ export default class Draw {
     ctx.restore();
   }
 
+  // 文字
+  drawText(vector) {
+    help.setVectorStyle(this.context, vector);
+    this.context.fillStyle = vector.color
+    this.context.font = `${vector.fontSize}px Microsoft YaHei`
+    this.drawTextByInfo(vector.center, vector.value, 0, false);
+  }
+
   drawLine(vector) {
+    if (vector.category === "Arrow") {
+      return this.drawArrow(vector);
+    }
     let start = dataService.getPoint(vector.startId);
     start = coordinate.getScreenXY(start);
     let end = dataService.getPoint(vector.endId);
@@ -412,7 +497,6 @@ export default class Draw {
       vector,
       vector.category || vector.geoType
     );
-
     if (style.dash) {
       this.context.setLineDash(style.dash);
     }

+ 1 - 1
src/graphic/enum/UIEvents.js

@@ -14,7 +14,7 @@ const UIEvents = {
   //svg
   SVG: "svg",
   // 放大镜
-  magnifier: "magnifier",
+  Magnifier: "magnifier",
 
   // ----------道路------------
   // 单向单车道直路

+ 4 - 4
src/hook/useLaser.ts

@@ -1,10 +1,10 @@
-import { sdkFactory, SDK, SDKProps, DensityType, Pos3D, Mode } from "@/sdk";
-import { watch, watchEffect } from "vue";
+import { sdkFactory, SDK, SDKProps, Pos3D, Mode } from "@/sdk";
 import { store } from "@/store";
-import { loadLib, toRawType } from "@/utils";
+import { loadLib } from "@/utils";
 import { Message } from "@kankan/components/index";
-import { ui18n } from "@/lang/index";
+import { ui18n } from "@/lang";
 import { DataSetAtom } from "@/sdk";
+import {laserModeStack} from "@/hook/custom";
 
 let sdk: SDK;
 export const useSDK = () => sdk;

+ 1 - 0
src/sdk/types/sdk.ts

@@ -244,6 +244,7 @@ export type Scene = Base & {
     pointsDatasets: string[],
     sid: string
   ): Measure;
+  trackScenePos: () => { promise: Promise<Pos3D>, quit: ()  => void}
   comeToMeasure: (measure: Measure) => Promise<void>;
   comeToTag: (pos: Pos3D) => Promise<void>;
 

+ 1 - 1
src/store/sync.ts

@@ -20,7 +20,7 @@ axios.get("/attach/sceneStore")
 
 export const updateSceneStore = debounce((data) => {
   axios.post("sceneStore", data)
-})
+}, 1000)
 
 const syncSceneStore = () => {
   return watch(

+ 35 - 0
src/views/graphic/container.vue

@@ -9,6 +9,7 @@
 <script setup lang="ts">
 import {onMounted, ref} from "vue";
 import {setCanvas} from "@/hook/useGraphic";
+import { draw } from '@/graphic/Renderer/Draw'
 
 const drawCanvasRef = ref<HTMLCanvasElement>();
 const setCanvasSize = () => {
@@ -19,6 +20,40 @@ const setCanvasSize = () => {
 onMounted(() => {
   setCanvasSize();
   setCanvas(drawCanvasRef.value);
+  // setTimeout(() =>{
+  //   draw.drawArrow({
+  //     start: {x: 300, y: 100},
+  //     end: {x: 150, y: 200},
+  //     geoType: "Arrow",
+  //     color: 'blue'
+  //   })
+  //
+  //
+  //
+  //   draw.drawCircle({
+  //     geoType: 'Circle',
+  //     radius: 10,
+  //     color: 'blue',
+  //     center: {
+  //     x: 200,
+  //     y: 200
+  //     }
+  //   })
+  //
+  //   draw.drawMagnifier({
+  //     position: { x: 150, y: 200 },
+  //     popPosition: { x: 250, y: 300 },
+  //     geoType: "Magnifier"
+  //   })
+  //
+  //   draw.drawText({
+  //     geoType: 'Text',
+  //     color: 'red',
+  //     fontSize: 14,
+  //     value: "啊啊啊在",
+  //     center: { x: 200, y: 200}
+  //   })
+  // }, 1000)
 });
 </script>
 

+ 1 - 1
src/views/graphic/menus.ts

@@ -101,7 +101,7 @@ export const photoMenusRaw: MenusRaw = [
   { key: UIType.Text, text: "文字" },
   { key: UIType.Circle, text: "圈出" },
   { key: UIType.Arrow, text: "箭头" },
-  { key: UIType.magnifier, text: "放大镜" },
+  { key: UIType.Magnifier, text: "放大镜" },
 ]
 
 

+ 1 - 0
src/views/scene/covers/actions.vue

@@ -33,6 +33,7 @@ defineProps<{ menus: ActionItem[] }>()
   left: 50%;
   transform: translateX(-50%);
   display: flex;
+  z-index: 2;
 
   .action {
     position: static;

+ 1 - 1
src/views/scene/covers/cover.vue

@@ -90,7 +90,7 @@ onUnmounted(() => {
 <style scoped lang="scss">
 .cover-layout {
   position: absolute;
-  z-index: 999;
+  z-index: 1;
   transform: translate(-50%, -100%);
   cursor: move;
 }

+ 5 - 16
src/views/scene/linkage/cover.ts

@@ -1,24 +1,13 @@
-import {Component, Ref, watchEffect} from "vue";
 import {useSDK} from "@/hook";
 import {CoordType, Pos, Pos3D} from "@/sdk";
 
 
 export const getCoverPos = (onComplete: (pos: Pos3D) => void) => {
   const sdk = useSDK();
-  const canvas = sdk.scene.el
-  const layout = canvas.parentElement
-
-  const downHandler = ev => {
-    const screenPos = { x: ev.offsetX, y: ev.offsetY }
-    const pos = sdk.coordTransform(CoordType.SCENE_SCREEN, screenPos, CoordType.LOCAL)
-    onComplete(pos as Pos3D)
-  }
-  const upHandler = () => {
-    canvas.removeEventListener("mousedown", downHandler)
-    canvas.removeEventListener("mouseup", upHandler)
+  const result = sdk.scene.trackScenePos()
+  result.promise.then(onComplete)
+  return () => {
+    result.quit()
+    onComplete(null)
   }
-  canvas.addEventListener("mousedown", downHandler)
-  canvas.addEventListener("mouseup", upHandler)
-
-  return upHandler
 }

+ 2 - 1
src/views/scene/menus/actions.ts

@@ -12,6 +12,7 @@ import Message from "@/components/base/components/message/message.vue";
 
 const trackPosMenuAction = (onComplete: () => void, onAddStore: (pos: Pos3D) => void) => {
   customMap.magnifier = true
+
   const onCleanup = getCoverPos(pos => {
     onComplete()
     onAddStore(pos)
@@ -124,7 +125,7 @@ export const joinActions = (activeKey: Ref<string>) => {
   return watch(
     () => activeKey.value,
     (key, oldKey, onCleanup) => {
-      if (key) {
+      if (key && menuActions[key]) {
         const menu = findMenuByKey(key as any)
         const cleanup = menuActions[key](menu, () => {
           if (!menu.continued) {

+ 1 - 0
src/views/scene/menus/pane.vue

@@ -50,5 +50,6 @@ onUnmounted(joinActions(store.itemActiveKey));
   left: var(--boundMargin);
   top: 50%;
   transform: translateY(-50%);
+  z-index: 2;
 }
 </style>

+ 5 - 2
src/views/scene/photo.vue

@@ -29,6 +29,8 @@ const photo = genUseLoading(async () => {
   await nextTick();
   const handler = () => {
     coverRef.value.removeEventListener("animationend", handler)
+
+    tempPhoto.value = null
   }
   coverRef.value.addEventListener("animationend", handler)
 })
@@ -37,6 +39,7 @@ const photo = genUseLoading(async () => {
 <style scoped lang="scss">
 .photo-layout {
   position: absolute;
+  z-index: 2;
   right: var(--boundMargin);
   top: 50%;
   transform: translateY(-50%);
@@ -95,8 +98,8 @@ const photo = genUseLoading(async () => {
     width: 48px;
     height: 48px;
     margin-left: -24px;
-    border-radius: 24px;
-    z-index: 2
+    border-radius: 50%;
+    z-index: 3
   }
 
   70% {