1
jhzh
2026-05-29 bbf6d337c9641c0d1bf2c57f05310e59c104990b
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
118
119
120
/**
 * 自定义绘图图形模板:矩形、三角形、平行四边形
 * 供 klinecharts addShapeTemplate 使用
 */
 
// 矩形:两点为对角线端点,totalStep=3 表示点击2次完成
export const rectShape = {
  name: 'rect',
  totalStep: 3,
  checkEventCoordinateOnShape: ({ dataSource, eventCoordinate }) => {
    if (!dataSource || dataSource.length < 1 || !dataSource[0].length) return false
    const points = dataSource[0]
    if (points.length < 4) return false
    const xs = points.map(p => p.x)
    const ys = points.map(p => p.y)
    const minX = Math.min(...xs)
    const maxX = Math.max(...xs)
    const minY = Math.min(...ys)
    const maxY = Math.max(...ys)
    return eventCoordinate.x >= minX - 4 && eventCoordinate.x <= maxX + 4 &&
      eventCoordinate.y >= minY - 4 && eventCoordinate.y <= maxY + 4
  },
  createShapeDataSource: ({ coordinates }) => {
    if (coordinates.length < 2) return []
    const [c1, c2] = coordinates
    const minX = Math.min(c1.x, c2.x)
    const maxX = Math.max(c1.x, c2.x)
    const minY = Math.min(c1.y, c2.y)
    const maxY = Math.max(c1.y, c2.y)
    const polygon = [
      { x: minX, y: minY },
      { x: maxX, y: minY },
      { x: maxX, y: maxY },
      { x: minX, y: maxY }
    ]
    return [{
      type: 'polygon',
      isDraw: true,
      isCheck: true,
      dataSource: [polygon]
    }]
  }
}
 
// 三角形:三个顶点,totalStep=4 表示点击3次完成
export const triangleShape = {
  name: 'triangle',
  totalStep: 4,
  checkEventCoordinateOnShape: ({ dataSource, eventCoordinate }) => {
    if (!dataSource || dataSource.length < 1 || !dataSource[0].length) return false
    const points = dataSource[0]
    if (points.length < 3) return false
    const getTriangleSquare = (p1, p2, p3) => {
      const x1 = Math.abs(p2.x - p1.x)
      const y1 = Math.abs(p2.y - p1.y)
      const x2 = Math.abs(p3.x - p1.x)
      const y2 = Math.abs(p3.y - p1.y)
      return Math.abs(x1 * y2 - x2 * y1) / 2
    }
    const square = getTriangleSquare(points[0], points[1], points[2])
    const compareSquare = getTriangleSquare(points[0], points[1], eventCoordinate) +
      getTriangleSquare(points[0], points[2], eventCoordinate) +
      getTriangleSquare(points[1], points[2], eventCoordinate)
    return Math.abs(square - compareSquare) < 4
  },
  createShapeDataSource: ({ coordinates }) => {
    if (coordinates.length < 3) return []
    const polygon = coordinates.slice(0, 3)
    return [{
      type: 'polygon',
      isDraw: true,
      isCheck: true,
      dataSource: [polygon]
    }]
  }
}
 
function getTriangleSquare(p1, p2, p3) {
  const x1 = Math.abs(p2.x - p1.x)
  const y1 = Math.abs(p2.y - p1.y)
  const x2 = Math.abs(p3.x - p1.x)
  const y2 = Math.abs(p3.y - p1.y)
  return Math.abs(x1 * y2 - x2 * y1) / 2
}
 
function pointInTriangle(p1, p2, p3, pt) {
  const square = getTriangleSquare(p1, p2, p3)
  const sum = getTriangleSquare(p1, p2, pt) + getTriangleSquare(p1, p3, pt) + getTriangleSquare(p2, p3, pt)
  return Math.abs(square - sum) < 4
}
 
// 平行四边形:前三点确定,第四点 = p2 + (p3 - p1)
export const parallelogramShape = {
  name: 'parallelogram',
  totalStep: 4,
  checkEventCoordinateOnShape: ({ dataSource, eventCoordinate }) => {
    if (!dataSource || dataSource.length < 1 || !dataSource[0].length) return false
    const points = dataSource[0]
    if (points.length < 4) return false
    return pointInTriangle(points[0], points[1], points[2], eventCoordinate) ||
      pointInTriangle(points[0], points[2], points[3], eventCoordinate)
  },
  createShapeDataSource: ({ coordinates }) => {
    if (coordinates.length < 3) return []
    const [p1, p2, p3] = coordinates
    const p4 = {
      x: p2.x + (p3.x - p1.x),
      y: p2.y + (p3.y - p1.y)
    }
    const polygon = [p1, p2, p4, p3]
    return [{
      type: 'polygon',
      isDraw: true,
      isCheck: true,
      dataSource: [polygon]
    }]
  }
}
 
export const customShapeTemplates = [rectShape, triangleShape, parallelogramShape]