Browse Source

添加正多边形

liwei 1 year ago
parent
commit
bb623b1490

+ 128 - 0
src/modules/editor/components/CompUI/basicUI/PolygonNormal/component.tsx

@@ -0,0 +1,128 @@
+import { defineComponent, onMounted , ref, effect} from "vue";
+import { string } from "vue-types";
+import { useCompData } from ".";
+import { useEditor } from "../../../..";
+import { View } from "../View";
+import { CompUI } from "../..";
+import { values } from "lodash";
+import { Angle } from "@/modules/editor/controllers/SelectCtrl/objects/mathUtils";
+
+function findNearestPoint(points: number[][], w:number, h:number, sx:number, sy:number) {
+   const n = points.length;
+   let minv = 100000;
+    let minIndex = -1;
+    const positions = []
+
+   for(let i=0; i<n; i++) {
+      const p = points[i];
+      const x = w *p[0];
+      const y = h *p[1];
+      positions.push([x, y]);
+
+      const ln = (sx-x)*(sx-x) + (sy-y)*(sy-y);
+      if ( ln < minv ) {
+        minIndex = i;
+        minv = ln;
+         if(!(sx < (x -10) || sx > (x + 10) || sy < (y -10) || sy > (y+10) ) ) {
+            return {clicked: true, index: i};
+         }
+      }
+   }   
+
+   let preIndex = minIndex -1;
+   if (preIndex < 0 ) preIndex = n-1;
+   let afterIndex = minIndex + 1;
+   if ( afterIndex >= n) afterIndex = 0;
+
+   const currV = {x:sx-positions[minIndex][0], y:sy-positions[minIndex][1]};
+   const preV = {x:positions[preIndex][0]-positions[minIndex][0], y:positions[preIndex][1]-positions[minIndex][1]}
+   const afterV = {x:positions[afterIndex][0]-positions[minIndex][0], y:positions[afterIndex][1]-positions[minIndex][1]}
+
+  const a1 =  Angle(currV, preV)
+  const a2 =  Angle(currV, afterV);
+
+  if (a1 < a2) {
+    return {index: preIndex};
+  }
+
+  return {index: minIndex};
+}
+
+export const Component = defineComponent({
+  props: {
+    compId: string().isRequired,
+  },
+  setup(props) {
+    const data = useCompData(props.compId);
+    const canvasRef =  ref<HTMLCanvasElement>();
+
+    onMounted(()=>{
+        effect(draw);
+    })
+
+    function drawPoly(ctx:CanvasRenderingContext2D, n:number, cx:number, cy:number, size:number) {
+        ctx.beginPath();
+        let degree = (2 *Math.PI) / n 
+        for (let i = 0; i<n; i++) {
+            const a = i*degree - Math.PI / 2.0;
+            const x = Math.cos(a), y = Math.sin(a);
+            ctx.lineTo(x*size + cx, y*size + cy)
+        }
+        ctx.closePath();
+
+    }
+
+    function draw() {
+        const canvas = canvasRef.value as HTMLCanvasElement;
+        if (!canvas) return;
+
+        const ctx = canvasRef.value?.getContext("2d") as CanvasRenderingContext2D;
+
+        const width = data.layout.size[0];
+        const height = data.layout.size[1];
+        canvas.width = Math.ceil(Math.max(1, width));
+        canvas.height = Math.ceil(Math.max(1, height));
+        ctx.clearRect(0, 0, canvas.width, canvas.height);
+        ctx.lineWidth = data.value.lineWidth;
+        ctx.save();
+
+        if (data.value.reverseFill) {
+            ctx.fillStyle = data.value.fillColor;
+            ctx.fillRect(0, 0, canvas.width, canvas.height);
+        }
+
+        ctx.strokeStyle = data.value.lineColor;
+
+        const padding = data.value.lineWidth;
+
+        ctx.lineJoin = "round";
+
+        drawPoly(ctx, data.value.edges, width/2.0, height / 2.0, (Math.min(width, height) - padding) / 2.0)
+
+        if (data.value.lineWidth !== 0) {
+            ctx.stroke();
+        }
+
+        if (data.value.isFill)    {
+            let bColor = data.value.fillColor;
+            if (!bColor) bColor = data.value.lineColor;
+            ctx.fillStyle = bColor;
+            if (data.value.reverseFill) {
+                ctx.fillStyle = "red";
+                // 设置剪切区域
+                ctx.clip();
+                // 将当前路径指定的区域颜色扣除
+                ctx.globalCompositeOperation = "destination-out";
+            }
+            ctx.fill();
+        }
+        ctx.restore();
+    }
+
+    return () => (
+      <View compId={props.compId}>
+         <canvas ref={canvasRef} style={{width:"100%", height: "100%"}}> </canvas>
+      </View>
+    );
+  },
+});

+ 73 - 0
src/modules/editor/components/CompUI/basicUI/PolygonNormal/index.ts

@@ -0,0 +1,73 @@
+import { Dict_Imgs } from "@/dict";
+import { createAttrsForm } from "../../defines/createAttrsForm";
+import { createCompHooks } from "../../defines/createCompHooks";
+import { InputNumber, Switch } from "ant-design-vue";
+import { createColorOpts } from "../../defines/formOpts/createColorOpts";
+import Slider from "../../formItems/Slider";
+
+export { Component } from "./component";
+
+export const options = {
+  name: "正多边形",
+  thumbnail: require("@/modules/editor/assets/icons/polygon.svg"),
+};
+
+export const { createComp, useCompData } = createCompHooks({
+  value: {
+    lineColor: "black",
+    lineWidth: 1,
+    isFill: false,
+    fillColor: "black",
+    points: [],
+    isClose: true,
+    reverseFill: false,
+    edges: 6
+  },
+  layout: {
+    size: [400, 400],
+  },
+});
+
+export const Form = createAttrsForm([
+
+    {
+        label: "边数",
+        dataIndex: "value.edges",
+        component: Slider,
+        props: {
+            defaultValue: 0,
+            min: 3,
+            max: 36,
+            step: 1,
+          },
+    },
+
+  {
+    label: "线宽",
+    dataIndex: "value.lineWidth",
+    component: InputNumber,
+  },
+  {
+    label:"颜色",
+    dataIndex: "value.lineColor",
+    ...createColorOpts(),
+  },
+  {
+    label: "是否填充",
+    dataIndex: "value.isFill",
+    component: "Switch",
+  },
+  {
+    label:"填充颜色",
+    dataIndex: "value.fillColor",
+    ...createColorOpts(),
+    isVisible: (value, data) => data?.value?.isFill == true,
+  },
+  {
+    label: "反向填充",
+    dataIndex: "value.reverseFill",
+    component: "Switch",
+    isVisible: (value, data) => data?.value?.isFill == true,
+  },
+  
+]);

+ 1 - 0
src/modules/editor/components/CompUI/basicUI/index.ts

@@ -11,5 +11,6 @@ export * as Arc from "./Arc";
 export * as Ellipse from "./Ellipse";
 export * as Triangle from "./Triangle";
 export * as Polygon from "./Polygon";
+export * as PolygonNormal from "./PolygonNormal";
 export * as Curve from "./Curve";
 export * as Map from "./Map";

+ 1 - 1
src/modules/editor/components/Viewport/Slider/SliderLeft/BaseComp.tsx

@@ -13,7 +13,7 @@ export default defineComponent({
 
     const state = useReactive(() => ({
       basicComps() {
-        return ["Text", "Image", "Video", "Web3D",  "Line", "Arc", "Ellipse", "Triangle", "Rectage", "Polygon", "Curve", "Map"].map(
+        return ["Text", "Image", "Video", "Web3D",  "Line", "Arc", "Ellipse", "Triangle", "Rectage", "Polygon","PolygonNormal", "Curve", "Map"].map(
           (key) => compUICtrl.state.components.get(key) as any
         );
       },