Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

polyline.tsx 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import { v4 as uuid } from "uuid"
  2. import * as vec from "utils/vec"
  3. import { PolylineShape, ShapeType } from "types"
  4. import { createShape } from "./index"
  5. import { intersectPolylineBounds } from "utils/intersections"
  6. import { boundsCollide, boundsContained } from "utils/bounds"
  7. const polyline = createShape<PolylineShape>({
  8. boundsCache: new WeakMap([]),
  9. create(props) {
  10. return {
  11. id: uuid(),
  12. type: ShapeType.Polyline,
  13. isGenerated: false,
  14. name: "Polyline",
  15. parentId: "page0",
  16. childIndex: 0,
  17. point: [0, 0],
  18. points: [[0, 0]],
  19. rotation: 0,
  20. style: {},
  21. ...props,
  22. }
  23. },
  24. render({ id, points }) {
  25. return <polyline id={id} points={points.toString()} />
  26. },
  27. getBounds(shape) {
  28. if (this.boundsCache.has(shape)) {
  29. return this.boundsCache.get(shape)
  30. }
  31. let minX = 0
  32. let minY = 0
  33. let maxX = 0
  34. let maxY = 0
  35. for (let [x, y] of shape.points) {
  36. minX = Math.min(x, minX)
  37. minY = Math.min(y, minY)
  38. maxX = Math.max(x, maxX)
  39. maxY = Math.max(y, maxY)
  40. }
  41. const bounds = {
  42. minX: minX + shape.point[0],
  43. minY: minY + shape.point[1],
  44. maxX: maxX + shape.point[0],
  45. maxY: maxY + shape.point[1],
  46. width: maxX - minX,
  47. height: maxY - minY,
  48. }
  49. this.boundsCache.set(shape, bounds)
  50. return bounds
  51. },
  52. hitTest(shape, point) {
  53. let pt = vec.sub(point, shape.point)
  54. let prev = shape.points[0]
  55. for (let i = 1; i < shape.points.length; i++) {
  56. let curr = shape.points[i]
  57. if (vec.distanceToLineSegment(prev, curr, pt) < 4) {
  58. return true
  59. }
  60. prev = curr
  61. }
  62. return false
  63. },
  64. hitTestBounds(this, shape, bounds) {
  65. const shapeBounds = this.getBounds(shape)
  66. return (
  67. boundsContained(shapeBounds, bounds) ||
  68. (boundsCollide(shapeBounds, bounds) &&
  69. intersectPolylineBounds(
  70. shape.points.map((point) => vec.add(point, shape.point)),
  71. bounds
  72. ).length > 0)
  73. )
  74. },
  75. rotate(shape) {
  76. return shape
  77. },
  78. translate(shape, delta) {
  79. shape.point = vec.add(shape.point, delta)
  80. return shape
  81. },
  82. scale(shape, scale: number) {
  83. return shape
  84. },
  85. stretch(shape, scaleX: number, scaleY: number) {
  86. return shape
  87. },
  88. transform(
  89. shape,
  90. bounds,
  91. { initialShape, initialShapeBounds, isFlippedX, isFlippedY }
  92. ) {
  93. shape.points = shape.points.map((_, i) => {
  94. const [x, y] = initialShape.points[i]
  95. return [
  96. bounds.width *
  97. (isFlippedX
  98. ? 1 - x / initialShapeBounds.width
  99. : x / initialShapeBounds.width),
  100. bounds.height *
  101. (isFlippedY
  102. ? 1 - y / initialShapeBounds.height
  103. : y / initialShapeBounds.height),
  104. ]
  105. })
  106. shape.point = [bounds.minX, bounds.minY]
  107. return shape
  108. },
  109. canTransform: true,
  110. })
  111. export default polyline