Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

rectangle.tsx 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import { v4 as uuid } from "uuid"
  2. import * as vec from "utils/vec"
  3. import { RectangleShape, ShapeType } from "types"
  4. import { createShape } from "./index"
  5. import { boundsCollidePolygon, boundsContainPolygon } from "utils/bounds"
  6. import { getBoundsFromPoints, rotateBounds, translateBounds } from "utils/utils"
  7. const rectangle = createShape<RectangleShape>({
  8. boundsCache: new WeakMap([]),
  9. create(props) {
  10. return {
  11. id: uuid(),
  12. type: ShapeType.Rectangle,
  13. isGenerated: false,
  14. name: "Rectangle",
  15. parentId: "page0",
  16. childIndex: 0,
  17. point: [0, 0],
  18. size: [1, 1],
  19. rotation: 0,
  20. style: {
  21. fill: "rgba(142, 143, 142, 1.000)",
  22. stroke: "#000",
  23. },
  24. ...props,
  25. }
  26. },
  27. render({ id, size }) {
  28. return <rect id={id} width={size[0]} height={size[1]} />
  29. },
  30. getBounds(shape) {
  31. if (!this.boundsCache.has(shape)) {
  32. const [width, height] = shape.size
  33. const bounds = {
  34. minX: 0,
  35. maxX: width,
  36. minY: 0,
  37. maxY: height,
  38. width,
  39. height,
  40. }
  41. this.boundsCache.set(shape, bounds)
  42. }
  43. return translateBounds(this.boundsCache.get(shape), shape.point)
  44. },
  45. getRotatedBounds(shape) {
  46. const b = this.getBounds(shape)
  47. const center = [b.minX + b.width / 2, b.minY + b.height / 2]
  48. // Rotate corners of the shape, then find the minimum among those points.
  49. const rotatedCorners = [
  50. [b.minX, b.minY],
  51. [b.maxX, b.minY],
  52. [b.maxX, b.maxY],
  53. [b.minX, b.maxY],
  54. ].map((point) => vec.rotWith(point, center, shape.rotation))
  55. return getBoundsFromPoints(rotatedCorners)
  56. },
  57. getCenter(shape) {
  58. const bounds = this.getRotatedBounds(shape)
  59. return [bounds.minX + bounds.width / 2, bounds.minY + bounds.height / 2]
  60. },
  61. hitTest(shape) {
  62. return true
  63. },
  64. hitTestBounds(shape, brushBounds) {
  65. const b = this.getBounds(shape)
  66. const center = [b.minX + b.width / 2, b.minY + b.height / 2]
  67. const rotatedCorners = [
  68. [b.minX, b.minY],
  69. [b.maxX, b.minY],
  70. [b.maxX, b.maxY],
  71. [b.minX, b.maxY],
  72. ].map((point) => vec.rotWith(point, center, shape.rotation))
  73. return (
  74. boundsContainPolygon(brushBounds, rotatedCorners) ||
  75. boundsCollidePolygon(brushBounds, rotatedCorners)
  76. )
  77. },
  78. rotate(shape) {
  79. return shape
  80. },
  81. translate(shape, delta) {
  82. shape.point = vec.add(shape.point, delta)
  83. return shape
  84. },
  85. scale(shape, scale) {
  86. return shape
  87. },
  88. transform(
  89. shape,
  90. shapeBounds,
  91. { initialShape, isSingle, initialShapeBounds, isFlippedX, isFlippedY }
  92. ) {
  93. // TODO: Apply rotation to single-selection items
  94. if (shape.rotation === 0 || isSingle) {
  95. shape.size = [shapeBounds.width, shapeBounds.height]
  96. shape.point = [shapeBounds.minX, shapeBounds.minY]
  97. } else {
  98. shape.size = vec.mul(
  99. initialShape.size,
  100. Math.min(
  101. shapeBounds.width / initialShapeBounds.width,
  102. shapeBounds.height / initialShapeBounds.height
  103. )
  104. )
  105. const newCenter = [
  106. shapeBounds.minX + shapeBounds.width / 2,
  107. shapeBounds.minY + shapeBounds.height / 2,
  108. ]
  109. shape.point = vec.sub(newCenter, vec.div(shape.size, 2))
  110. }
  111. // Rotation for flipped shapes
  112. shape.rotation = initialShape.rotation
  113. if (isFlippedX) {
  114. shape.rotation *= -1
  115. }
  116. if (isFlippedY) {
  117. shape.rotation *= -1
  118. }
  119. return shape
  120. },
  121. canTransform: true,
  122. })
  123. export default rectangle