您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

polyline.tsx 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import { v4 as uuid } from "uuid"
  2. import * as vec from "utils/vec"
  3. import { PolylineShape, ShapeType } from "types"
  4. import { registerShapeUtils } from "./index"
  5. import { intersectPolylineBounds } from "utils/intersections"
  6. import {
  7. boundsCollide,
  8. boundsContained,
  9. boundsContainPolygon,
  10. } from "utils/bounds"
  11. import { getBoundsFromPoints, translateBounds } from "utils/utils"
  12. import { colors } from "state/data"
  13. const polyline = registerShapeUtils<PolylineShape>({
  14. boundsCache: new WeakMap([]),
  15. create(props) {
  16. return {
  17. id: uuid(),
  18. type: ShapeType.Polyline,
  19. isGenerated: false,
  20. name: "Polyline",
  21. parentId: "page0",
  22. childIndex: 0,
  23. point: [0, 0],
  24. points: [[0, 0]],
  25. rotation: 0,
  26. style: {
  27. strokeWidth: 2,
  28. strokeLinecap: "round",
  29. strokeLinejoin: "round",
  30. },
  31. ...props,
  32. }
  33. },
  34. render({ id, points }) {
  35. return <polyline id={id} points={points.toString()} />
  36. },
  37. applyStyles(shape, style) {
  38. Object.assign(shape.style, style)
  39. return this
  40. },
  41. getBounds(shape) {
  42. if (!this.boundsCache.has(shape)) {
  43. const bounds = getBoundsFromPoints(shape.points)
  44. this.boundsCache.set(shape, bounds)
  45. }
  46. return translateBounds(this.boundsCache.get(shape), shape.point)
  47. },
  48. getRotatedBounds(shape) {
  49. return this.getBounds(shape)
  50. },
  51. getCenter(shape) {
  52. const bounds = this.getBounds(shape)
  53. return [bounds.minX + bounds.width / 2, bounds.minY + bounds.height / 2]
  54. },
  55. hitTest(shape, point) {
  56. let pt = vec.sub(point, shape.point)
  57. let prev = shape.points[0]
  58. for (let i = 1; i < shape.points.length; i++) {
  59. let curr = shape.points[i]
  60. if (vec.distanceToLineSegment(prev, curr, pt) < 4) {
  61. return true
  62. }
  63. prev = curr
  64. }
  65. return false
  66. },
  67. hitTestBounds(this, shape, brushBounds) {
  68. const b = this.getBounds(shape)
  69. const center = [b.minX + b.width / 2, b.minY + b.height / 2]
  70. const rotatedCorners = [
  71. [b.minX, b.minY],
  72. [b.maxX, b.minY],
  73. [b.maxX, b.maxY],
  74. [b.minX, b.maxY],
  75. ].map((point) => vec.rotWith(point, center, shape.rotation))
  76. return (
  77. boundsContainPolygon(brushBounds, rotatedCorners) ||
  78. intersectPolylineBounds(
  79. shape.points.map((point) => vec.add(point, shape.point)),
  80. brushBounds
  81. ).length > 0
  82. )
  83. },
  84. rotateTo(shape, rotation) {
  85. shape.rotation = rotation
  86. return this
  87. },
  88. translateTo(shape, point) {
  89. shape.point = point
  90. return this
  91. },
  92. transform(shape, bounds, { initialShape, scaleX, scaleY }) {
  93. const initialShapeBounds = this.getBounds(initialShape)
  94. shape.points = shape.points.map((_, i) => {
  95. const [x, y] = initialShape.points[i]
  96. return [
  97. bounds.width *
  98. (scaleX < 0
  99. ? 1 - x / initialShapeBounds.width
  100. : x / initialShapeBounds.width),
  101. bounds.height *
  102. (scaleY < 0
  103. ? 1 - y / initialShapeBounds.height
  104. : y / initialShapeBounds.height),
  105. ]
  106. })
  107. shape.point = [bounds.minX, bounds.minY]
  108. return this
  109. },
  110. transformSingle(shape, bounds, info) {
  111. this.transform(shape, bounds, info)
  112. return this
  113. },
  114. setParent(shape, parentId) {
  115. shape.parentId = parentId
  116. return this
  117. },
  118. setChildIndex(shape, childIndex) {
  119. shape.childIndex = childIndex
  120. return this
  121. },
  122. canTransform: true,
  123. canChangeAspectRatio: true,
  124. })
  125. export default polyline