Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

circle.tsx 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import { v4 as uuid } from "uuid"
  2. import * as vec from "utils/vec"
  3. import { CircleShape, ShapeType, TransformCorner, TransformEdge } from "types"
  4. import { createShape } from "./index"
  5. import { boundsContained } from "utils/bounds"
  6. import { intersectCircleBounds } from "utils/intersections"
  7. import { pointInCircle } from "utils/hitTests"
  8. const circle = createShape<CircleShape>({
  9. boundsCache: new WeakMap([]),
  10. create(props) {
  11. return {
  12. id: uuid(),
  13. type: ShapeType.Circle,
  14. isGenerated: false,
  15. name: "Circle",
  16. parentId: "page0",
  17. childIndex: 0,
  18. point: [0, 0],
  19. rotation: 0,
  20. radius: 20,
  21. style: {},
  22. ...props,
  23. }
  24. },
  25. render({ id, radius }) {
  26. return <circle id={id} cx={radius} cy={radius} r={radius} />
  27. },
  28. getBounds(shape) {
  29. if (this.boundsCache.has(shape)) {
  30. return this.boundsCache.get(shape)
  31. }
  32. const {
  33. point: [x, y],
  34. radius,
  35. } = shape
  36. const bounds = {
  37. minX: x,
  38. maxX: x + radius * 2,
  39. minY: y,
  40. maxY: y + radius * 2,
  41. width: radius * 2,
  42. height: radius * 2,
  43. }
  44. this.boundsCache.set(shape, bounds)
  45. return bounds
  46. },
  47. hitTest(shape, point) {
  48. return pointInCircle(
  49. point,
  50. vec.addScalar(shape.point, shape.radius),
  51. shape.radius
  52. )
  53. },
  54. hitTestBounds(shape, bounds) {
  55. const shapeBounds = this.getBounds(shape)
  56. return (
  57. boundsContained(shapeBounds, bounds) ||
  58. intersectCircleBounds(
  59. vec.addScalar(shape.point, shape.radius),
  60. shape.radius,
  61. bounds
  62. ).length > 0
  63. )
  64. },
  65. rotate(shape) {
  66. return shape
  67. },
  68. translate(shape, delta) {
  69. shape.point = vec.add(shape.point, delta)
  70. return shape
  71. },
  72. scale(shape, scale) {
  73. return shape
  74. },
  75. transform(shape, bounds, { anchor }) {
  76. // Set the new corner or position depending on the anchor
  77. switch (anchor) {
  78. case TransformCorner.TopLeft: {
  79. shape.radius = Math.min(bounds.width, bounds.height) / 2
  80. shape.point = [
  81. bounds.maxX - shape.radius * 2,
  82. bounds.maxY - shape.radius * 2,
  83. ]
  84. break
  85. }
  86. case TransformCorner.TopRight: {
  87. shape.radius = Math.min(bounds.width, bounds.height) / 2
  88. shape.point = [bounds.minX, bounds.maxY - shape.radius * 2]
  89. break
  90. }
  91. case TransformCorner.BottomRight: {
  92. shape.radius = Math.min(bounds.width, bounds.height) / 2
  93. shape.point = [bounds.minX, bounds.minY]
  94. break
  95. }
  96. case TransformCorner.BottomLeft: {
  97. shape.radius = Math.min(bounds.width, bounds.height) / 2
  98. shape.point = [bounds.maxX - shape.radius * 2, bounds.minY]
  99. break
  100. }
  101. case TransformEdge.Top: {
  102. shape.radius = bounds.height / 2
  103. shape.point = [
  104. bounds.minX + (bounds.width / 2 - shape.radius),
  105. bounds.minY,
  106. ]
  107. break
  108. }
  109. case TransformEdge.Right: {
  110. shape.radius = bounds.width / 2
  111. shape.point = [
  112. bounds.maxX - shape.radius * 2,
  113. bounds.minY + (bounds.height / 2 - shape.radius),
  114. ]
  115. break
  116. }
  117. case TransformEdge.Bottom: {
  118. shape.radius = bounds.height / 2
  119. shape.point = [
  120. bounds.minX + (bounds.width / 2 - shape.radius),
  121. bounds.maxY - shape.radius * 2,
  122. ]
  123. break
  124. }
  125. case TransformEdge.Left: {
  126. shape.radius = bounds.width / 2
  127. shape.point = [
  128. bounds.minX,
  129. bounds.minY + (bounds.height / 2 - shape.radius),
  130. ]
  131. break
  132. }
  133. }
  134. return shape
  135. },
  136. canTransform: true,
  137. })
  138. export default circle