浏览代码

添加draw类别

bill 2 年之前
父节点
当前提交
4ef745d8d1

+ 43 - 6
src/graphic/CanvasStyle/default.js

@@ -16,7 +16,7 @@ const Lane = {
   dash: [8, 8],
 };
 
-const Arrow = {
+const ArrowLine = {
   lineWidth: 2,
   strokeStyle: "red",
 };
@@ -112,14 +112,33 @@ const GuideLine = {
   dash: [3, 2, 2],
 };
 const MeasureLine = {
-  strokeStyle: "#CED806",
-  lineWidth: 2,
+  strokeStyle: "#2F8FFF",
+  lineWidth: 4,
+  text: {
+    fillColor: "#fff",
+    padding: 6,
+    backColor: "#2F8FFF"
+  },
+
 };
 const BaseLine = {
-  strokeStyle: "#3290FF",
-  lineWidth: 2,
+  strokeStyle: "#000",
+  lineWidth: 1,
 };
 
+const BasePoint = {
+  strokeStyle: "rgba(0,0,0,0)",
+  fillStyle: "#000",
+  radius: 6,
+  lineWidth: 1,
+  out: {
+    strokeStyle: "#000",
+    fillStyle: "rgba(255,255,255,0)",
+    radius: 8,
+    lineWidth: 1,
+  }
+}
+
 const Element = {
   AddingPoint: {
     radius: 4,
@@ -151,6 +170,22 @@ const Element = {
   },
 };
 
+
+const TestPoint = {
+  strokeStyle: "rgba(0,0,0,0)",
+  fillStyle: "#fff",
+  radius: 6,
+  lineWidth: 1,
+  out: {
+    strokeStyle: "#3290FF",
+    fillStyle: "rgba(255,255,255,0)",
+    radius: 8,
+    lineWidth: 3,
+  }
+}
+
+
+
 export default {
   NormalLine,
   Road,
@@ -171,7 +206,9 @@ export default {
   MeasureLine,
   Measure,
   Element,
+  TestPoint,
   RoadPoint,
-  Arrow,
+  ArrowLine,
+  BasePoint,
   bgColor: "#fff",
 };

+ 36 - 2
src/graphic/CanvasStyle/focus.js

@@ -58,21 +58,55 @@ const CurveRoadEdge = {
   lineWidth: 2,
   strokeStyle: "#3290FF",
 };
-const Arrow = {
+const ArrowLine = {
   lineWidth: 2,
   strokeStyle: "red",
 };
+
+const BasePoint = {
+  strokeStyle: "rgba(0,0,0,0)",
+  fillStyle: "#3290FF",
+  radius: 6,
+  lineWidth: 1,
+  out: {
+    strokeStyle: "#3290FF",
+    fillStyle: "rgba(255,255,255,0)",
+    radius: 8,
+    lineWidth: 1,
+  }
+}
+
+
+const TestPoint = {
+  strokeStyle: "rgba(0,0,0,0)",
+  fillStyle: "#fff",
+  radius: 6,
+  lineWidth: 1,
+  out: {
+    strokeStyle: "#3290FF",
+    fillStyle: "rgba(255,255,255,0)",
+    radius: 8,
+    lineWidth: 3,
+  }
+}
+const BaseLine = {
+  strokeStyle: "#3290FF",
+  lineWidth: 1,
+};
 export default {
   Road,
   Text,
+  BasePoint,
   Point,
-  Arrow,
+  ArrowLine,
   RoadPoint,
   CurveRoadPoint,
   CrossPoint,
   CurveRoad,
+  TestPoint,
   RoadEdge,
   Magnifier,
+  BaseLine,
   NormalLine,
   CurveRoadEdge,
 };

+ 37 - 2
src/graphic/CanvasStyle/select.js

@@ -6,12 +6,16 @@ const Road = {
   strokeStyle: "#3290FF",
 };
 
+const BaseLine = {
+  strokeStyle: "#3290FF",
+  lineWidth: 1,
+};
 const NormalLine = {
   ...def.NormalLine,
   lineWidth: 2,
   strokeStyle: "#3290FF",
 };
-const Arrow = {
+const ArrowLine = {
   lineWidth: 2,
   strokeStyle: "red",
 };
@@ -58,16 +62,47 @@ const CrossPoint = {
   fillStyle: "#3290FF",
 };
 
+const BasePoint = {
+  strokeStyle: "rgba(0,0,0,0)",
+  fillStyle: "#3290FF",
+  radius: 6,
+  lineWidth: 1,
+  out: {
+    strokeStyle: "#3290FF",
+    fillStyle: "rgba(255,255,255,0)",
+    radius: 8,
+    lineWidth: 1,
+  }
+}
+
+const TestPoint = {
+  strokeStyle: "rgba(0,0,0,0)",
+  fillStyle: "#fff",
+  radius: 6,
+  lineWidth: 1,
+  out: {
+    strokeStyle: "#3290FF",
+    fillStyle: "rgba(255,255,255,0)",
+    radius: 8,
+    lineWidth: 3,
+  }
+}
+
+
+
 export default {
   Road,
   Text,
   Point,
+  TestPoint,
   RoadPoint,
   CurveRoadPoint,
   CrossPoint,
   CurveRoad,
+  BasePoint,
+  BaseLine,
   RoadEdge,
   NormalLine,
   CurveRoadEdge,
-  Arrow,
+  ArrowLine,
 };

+ 1 - 1
src/graphic/Geometry/Line.js

@@ -12,7 +12,7 @@ export default class Line extends Geometry {
     this.startId = startId;
     this.endId = endId;
     this.category = Settings.lineCategory;
-    this.arrowColor = Style.Arrow.strokeStyle; //箭头类型会用到
+    this.arrowColor = Style.ArrowLine.strokeStyle; //箭头类型会用到
     this.geoType = VectorType.Line;
     this.setId(vectorId);
   }

+ 176 - 34
src/graphic/Renderer/Draw.js

@@ -7,6 +7,7 @@ import { mathUtil } from "../Util/MathUtil.js";
 import ElementEvents from "../enum/ElementEvents.js";
 import { elementService } from "../Service/ElementService.js";
 import UIEvents from "@/graphic/enum/UIEvents.js";
+import VectorCategory from "@/graphic/enum/VectorCategory.js";
 
 const imgCache = {};
 const help = {
@@ -30,9 +31,10 @@ const help = {
           // item.type === VectorType[geoType] &&
           geoId === item.vectorId
         ) {
-          if (Style[attr] && Style[attr][geoType]) {
+          const style = Style[attr][geoType] || Style[attr][item.category]
+          if (Style[attr] && style) {
             currentAttr = attr;
-            return Style[attr][geoType];
+            return style;
           }
         }
         return prev;
@@ -40,8 +42,7 @@ const help = {
       currentAttr,
     ];
   },
-  setVectorStyle(ctx, vector, geoType = vector.geoType) {
-    const [styles, attr] = help.getVectorStyle(vector, geoType);
+  setStyle(ctx, styles) {
     for (const style in styles) {
       if (typeof styles[style] === "function") {
         styles[style](ctx, vector);
@@ -49,6 +50,20 @@ const help = {
         ctx[style] = styles[style];
       }
     }
+  },
+  setVectorStyle(ctx, vector, geoType = vector.geoType) {
+    let styles, attr
+    if (Array.isArray(geoType)) {
+      for (const type of geoType) {
+        [styles, attr] = help.getVectorStyle(vector, type);
+        if (styles) {
+          break;
+        }
+      }
+    } else {
+      [styles, attr] = help.getVectorStyle(vector, geoType);
+    }
+    help.setStyle(ctx, styles)
     return [styles, attr];
   },
   transformCoves(lines) {
@@ -99,6 +114,86 @@ const help = {
       };
     }));
   },
+  getTextCenter(ctx, txt) {
+    const text = ctx.measureText(txt);
+    const height = text.actualBoundingBoxAscent + text.actualBoundingBoxDescent
+    return {
+      width: text.width,
+      height,
+      x: text.width / 2,
+      y: -height / 2
+    }
+  },
+  // 绘制圆角矩形
+  roundRect(ctx, x, y, width, height, radius) {
+    ctx.beginPath();
+    ctx.moveTo(x + radius, y);
+    ctx.lineTo(x + width - radius, y);
+    ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
+    ctx.lineTo(x + width, y + height - radius);
+    ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
+    ctx.lineTo(x + radius, y + height);
+    ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
+    ctx.lineTo(x, y + radius);
+    ctx.quadraticCurveTo(x, y, x + radius, y);
+    ctx.closePath();
+  },
+  getRealDistance(p1, p2) {
+    return Math.round(mathUtil.getDistance(p1, p2) * 100) / 100
+  },
+  getPerpendicularPoint(p1, p2, p3, d) {
+    if (p1.x === p2.x) {
+      return {x: p3.x + d, y: p3.y}
+    } else if (p1.y === p2.y) {
+      return {x: p3.x, y: p3.y + d}
+    }
+
+    // 计算通过 p1 和 p2 的直线的斜率和截距
+    const slope = (p2.y - p1.y) / (p2.x - p1.x);
+    const intercept = p1.y - slope * p1.x;
+
+    // 计算垂直线的斜率和截距
+    const perpendicularSlope = -1 / slope;
+    const perpendicularIntercept = p3.y - perpendicularSlope * p3.x;
+
+    // 计算垂足点 p0
+    const x = (perpendicularIntercept - intercept) / (slope - perpendicularSlope);
+    const y = slope * x + intercept;
+    const p0 = { x, y };
+
+// 计算点 p4
+    const distance = d; // 指定距离
+    const dx = distance / Math.sqrt(1 + perpendicularSlope ** 2);
+    const dy = perpendicularSlope * dx;
+    return { x: p0.x + dx, y: p0.y + dy };
+  },
+  drawLineText(ctx, start, end, text, style) {
+    if (start.x > end.x) {
+      [start, end] = [end, start]
+    }
+
+    const angle = Math.atan2(end.y - start.y, end.x - start.x) * 180 / Math.PI;
+    const center = mathUtil.lineCenter(start, end)
+
+    ctx.save();
+    ctx.translate(center.x, center.y);
+    ctx.rotate(angle * Math.PI / 180);
+    const textCenter = help.getTextCenter(ctx, text)
+    const padding = style.padding;
+    help.roundRect(
+      ctx,
+      -textCenter.x - padding,
+      textCenter.y - padding,
+      textCenter.width + 2 * padding,
+      textCenter.height + 2 * padding,
+      (textCenter.height / 2) + padding
+    )
+    ctx.fillStyle = style.backColor
+    ctx.fill()
+    ctx.fillStyle = style.fillColor
+    ctx.fillText(text, -textCenter.x, -textCenter.y);
+    ctx.restore();
+  }
 };
 
 export default class Draw {
@@ -407,13 +502,10 @@ export default class Draw {
 
     ctx.save();
 
-    const [style] = help.setVectorStyle(this.context, vector, "Arrow");
+    const [style] = help.setVectorStyle(this.context, vector);
     if (vector.arrowColor) {
       ctx.strokeStyle = vector.arrowColor;
     }
-    ctx.beginPath();
-    ctx.moveTo(start.x, start.y);
-    ctx.lineTo(end.x, end.y);
 
     const dires =
       vector.category === UIEvents.MeasureLine
@@ -431,7 +523,7 @@ export default class Draw {
     ctx.stroke();
     ctx.restore();
 
-    if ([Style.Focus.Arrow, Style.Select.Arrow].includes(style)) {
+    if ([Style.Focus.ArrowLine, Style.Select.ArrowLine].includes(style)) {
       this.drawPoint(startReal);
       this.drawPoint(endReal);
     }
@@ -523,17 +615,29 @@ export default class Draw {
   drawPoint(vector) {
     const pt = coordinate.getScreenXY({ x: vector.x, y: vector.y });
     const ctx = this.context;
-    const [style] = help.setVectorStyle(ctx, vector, vector.geoType || "Point");
+    const [style] = help.setVectorStyle(
+      ctx,
+      vector,
+      [vector.category, vector.geoType, "Point"]
+
+    );
     if (vector.color) {
       ctx.strokeStyle = vector.color;
     }
-    const radius = help.getReal(vector.radius || style.radius);
-    ctx.save();
-    ctx.beginPath();
-    ctx.arc(pt.x, pt.y, radius, 0, Math.PI * 2, true);
-    ctx.stroke();
-    ctx.fill();
-    ctx.restore();
+    const draw = (style) => {
+      const radius = help.getReal(vector.radius || style.radius);
+      ctx.save();
+      ctx.beginPath();
+      ctx.arc(pt.x, pt.y, radius, 0, Math.PI * 2, true);
+      help.setStyle(ctx, style)
+      ctx.stroke();
+      ctx.fill();
+      ctx.restore();
+    }
+    draw(style)
+    if (style.out) {
+      draw(style.out)
+    }
 
     if (import.meta.env.DEV) {
       if (vector.vectorId) {
@@ -548,9 +652,10 @@ export default class Draw {
     setStyle && help.setVectorStyle(ctx, null, "Text");
 
     const pt = coordinate.getScreenXY(position);
-    const text = ctx.measureText(txt);
-    pt.x -= text.width / 2;
-    pt.y += (text.actualBoundingBoxAscent + text.actualBoundingBoxDescent) / 2;
+    const textCenter = help.getTextCenter(ctx, txt);
+    pt.x -= textCenter.x;
+    pt.y -= textCenter.y;
+
     if (angle) {
       ctx.translate(pt.x, pt.y);
       ctx.rotate(angle);
@@ -578,24 +683,53 @@ export default class Draw {
     this.context.font = oldFont;
   }
 
-  drawLineText(vector) {
+  drawLineText(vector, style) {
+    const startReal = dataService.getPoint(vector.startId);
+    const endReal = dataService.getPoint(vector.endId);
+    help.drawLineText(
+      this.context,
+      coordinate.getScreenXY(startReal),
+      coordinate.getScreenXY(endReal),
+      help.getRealDistance(startReal, endReal) + "m",
+      style
+    )
+  }
+
+  drawBaseLineLabel(vector) {
     const startReal = dataService.getPoint(vector.startId);
     const start = coordinate.getScreenXY(startReal);
     const endReal = dataService.getPoint(vector.endId);
     const end = coordinate.getScreenXY(endReal);
+    const point = mathUtil.translate(
+      end, start, end, mathUtil.getDistance(start, end) / 3
+    )
+    const p4 = help.getPerpendicularPoint(start, end, point, 30)
+    const ctx = this.context
+    ctx.beginPath();
+    const [style] = help.setVectorStyle(
+      this.context,
+      vector,
+      vector.category || vector.geoType
+    );
+    ctx.moveTo(point.x, point.y);
+    ctx.lineTo(p4.x, p4.y);
+    ctx.stroke();
 
-    const angle = Math.atan2(end.y - start.y, end.x - start.x) * 180 / Math.PI;
-    this.context.translate(start.x, start.y);
-    this.context.rotate(angle * Math.PI / 180);
-
-// 在路径上绘制文本
-    context.fillText('Hello World!', 0, 0);
+    const p5 = help.getPerpendicularPoint(start, end, point, 35)
+    help.drawLineText(
+      this.context,
+      help.getPerpendicularPoint(point, p5, p5, 10),
+      help.getPerpendicularPoint(point, p5, p5, -10),
+      "基准线",
+      {
+        padding: 6,
+        backColor: "rgba(0,0,0,0)",
+        fillColor: style.strokeStyle
+      }
+    )
   }
 
   drawLine(vector) {
-    if ([UIEvents.Arrow, UIEvents.MeasureFree].includes(vector.category)) {
-      return this.drawArrow(vector);
-    }
     const startReal = dataService.getPoint(vector.startId);
     const start = coordinate.getScreenXY(startReal);
     const endReal = dataService.getPoint(vector.endId);
@@ -617,10 +751,18 @@ export default class Draw {
     this.context.stroke();
     this.context.restore();
 
-    // if (attr) {
-    //   this.drawPoint(startReal)
-    //   this.drawPoint(endReal)
-    // }
+    switch (vector.category) {
+      case VectorCategory.Line.ArrowLine:
+        this.drawArrow(vector);
+        break
+      case VectorCategory.Line.BaseLine:
+        this.drawBaseLineLabel(vector)
+        break;
+      case VectorCategory.Line.MeasureLine:
+        this.drawLineText(vector, style.text)
+        break;
+    }
+
   }
 
   drawElementLine(element) {

+ 8 - 0
src/graphic/Util/MathUtil.js

@@ -1157,6 +1157,14 @@ export default class MathUtil {
       y: v1.y + v2.y,
     };
   }
+  // 中心点
+  lineCenter(v1, v2) {
+    const point = this.pointPlus(v1, v2)
+    return {
+      x: point.x / 2,
+      y: point.y / 2
+    }
+  }
   // 点放大
   pointScale(v, a) {
     return {

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

@@ -14,7 +14,7 @@ const UIEvents = {
 
   // 测量
   // 自由测量
-  MeasureFree: "MeasureLine",
+  NormalLocationMode: "NormalLocationMode",
   // 直角定位法
   AngleLocationMode: "AngleLocationMode",
   // 综合定位法

+ 1 - 1
src/views/graphic/geos/index.ts

@@ -8,7 +8,7 @@ import VectorCategory from "@/graphic/enum/VectorCategory";
 
 export default {
   [VectorType.ArrowLine]: Arrow,
-  [VectorCategory.Line.MeasureLine]: Arrow,
+  // [VectorCategory.Line.MeasureLine]: Arrow,
   [VectorCategory.Line.NormalLine]: Arrow,
   [VectorType.Text]: Text,
   [VectorType.Circle]: Circle,

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

@@ -77,7 +77,7 @@ export const templateMenusRaw = [
 export const measureMenusRaw = [
   { key: UIType.BaseLine, text: "基准线" },
   { key: UIType.BasePoint, text: "基准点" },
-  { key: UIType.MeasureFree, text: "自由测量" },
+  { key: UIType.NormalLocationMode, text: "自由测量" },
   {
     key: UIType.AngleLocationMode,
     text: "直角定位法",