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>
|
|