he wei
2025-06-03 a10f3b82e33756ed0cd62a0cbe83bab8674df16f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<script setup>
import { ref, computed } from "vue";
 
const props = defineProps({
    offset: {
        type: Array,
        default: () => [0, 0],
    },
    points: {
        type: Array,
        default: () => [
            [0, 0],
            [10, 10],
        ],
    },
    color: {
        type: String,
        default: "#804000",
    },
  roundCornerFlag: {
    type: Boolean,
    default: false
  },
    lineWidth: {
        type: Number,
        default: 2,
    },
    currColor: {
        type: String,
        default: "#0f0",
    },
  r: {
    type: [Number, String],
    default: 6
  },
});
 
function calcVectorProperties(A, B) {
  let [x0, y0] = A;
  let [x1, y1] = B;
  // 计算向量分量
  const dx = x1 - x0;
  const dy = y1 - y0;
  
  // 计算向量的模长(欧几里得距离)
  const magnitude = Math.sqrt(dx * dx + dy * dy);
  if (magnitude < props.r) {
    throw new Error('两点之间距离过近');
  }
  
  // 处理零向量情况(避免除以零)
  const normalizedVector = magnitude === 0 
      ? [0, 0]
      : [ dx / magnitude, dy / magnitude ];
  
  // 计算向量与x轴正方向的夹角(弧度)
  // Math.atan2 返回值范围:[-π, π]
  const angleRadians = Math.atan2(normalizedVector[1], normalizedVector[0]);
 
  // AB上离B点的距离r距离的点的坐标(x2, y2)
  const x2 = x1 - props.r * normalizedVector[0];
  const y2 = y1 - props.r * normalizedVector[1];
  
  return {
    normalizedVector,
    angleRadians,
    x2,
    y2
  };
}
 
 
const path = computed(() => {
    let points = props.points;
    let path = `M ${points[0].join(",")} `;
    for (let i = 1, len = points.length; i < len; i++) {
    let str = '';
    let p0 = points[i - 1],
    p1 = points[i],
    p2 = points[i + 1];
 
    if (props.roundCornerFlag) {
      if (i == len - 1) {
        str = ` L ${p1.join(",")} `;
      } else {
        let { x2, y2 } = calcVectorProperties(p0, p1);
        let { x2: x3, y2: y3 } = calcVectorProperties(p2, p1);
        str = ` L ${x2},${y2} Q ${p1.join(",")} ${x3},${y3} `;
      }
    } else {
      str = ` L ${points[i].join(",")} `
    }
        path += str;
    }
    return path;
});
const pointsStr = computed(() => {
    return props.points.join(" ");
});
</script>
 
<template>
  <g ref="g" :transform="'translate(' + offset.join(',') + ')'">
    <!-- <defs>
        <circle id="ball" :r="ballR" />
      </defs> -->
    <!-- <polyline
      :points="pointsStr"
      :stroke="color"
      :stroke-width="lineWidth"
      style="fill: none"
    /> -->
    <path :d="path" :stroke="color" :stroke-width="lineWidth" style="fill: none;"></path>
  </g>
</template>
 
<style scoped lang="less"></style>