Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

circle.tsx 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import { v4 as uuid } from 'uuid'
  2. import * as vec from 'utils/vec'
  3. import { CircleShape, ShapeType } from 'types'
  4. import { registerShapeUtils } from './index'
  5. import { boundsContained } from 'utils/bounds'
  6. import { intersectCircleBounds } from 'utils/intersections'
  7. import { pointInCircle } from 'utils/hitTests'
  8. import { translateBounds } from 'utils/utils'
  9. const circle = registerShapeUtils<CircleShape>({
  10. boundsCache: new WeakMap([]),
  11. create(props) {
  12. return {
  13. id: uuid(),
  14. type: ShapeType.Circle,
  15. isGenerated: false,
  16. name: 'Circle',
  17. parentId: 'page0',
  18. childIndex: 0,
  19. point: [0, 0],
  20. rotation: 0,
  21. radius: 1,
  22. style: {
  23. fill: '#c6cacb',
  24. stroke: '#000',
  25. },
  26. ...props,
  27. }
  28. },
  29. render({ id, radius, style }) {
  30. return (
  31. <circle
  32. id={id}
  33. cx={radius}
  34. cy={radius}
  35. r={Math.max(0, radius - Number(style.strokeWidth) / 2)}
  36. />
  37. )
  38. },
  39. applyStyles(shape, style) {
  40. Object.assign(shape.style, style)
  41. return this
  42. },
  43. getBounds(shape) {
  44. if (!this.boundsCache.has(shape)) {
  45. const { radius } = shape
  46. const bounds = {
  47. minX: 0,
  48. maxX: radius * 2,
  49. minY: 0,
  50. maxY: radius * 2,
  51. width: radius * 2,
  52. height: radius * 2,
  53. }
  54. this.boundsCache.set(shape, bounds)
  55. }
  56. return translateBounds(this.boundsCache.get(shape), shape.point)
  57. },
  58. getRotatedBounds(shape) {
  59. return this.getBounds(shape)
  60. },
  61. getCenter(shape) {
  62. return [shape.point[0] + shape.radius, shape.point[1] + shape.radius]
  63. },
  64. hitTest(shape, point) {
  65. return pointInCircle(
  66. point,
  67. vec.addScalar(shape.point, shape.radius),
  68. shape.radius
  69. )
  70. },
  71. hitTestBounds(shape, bounds) {
  72. const shapeBounds = this.getBounds(shape)
  73. return (
  74. boundsContained(shapeBounds, bounds) ||
  75. intersectCircleBounds(
  76. vec.addScalar(shape.point, shape.radius),
  77. shape.radius,
  78. bounds
  79. ).length > 0
  80. )
  81. },
  82. rotateTo(shape, rotation) {
  83. shape.rotation = rotation
  84. return this
  85. },
  86. translateTo(shape, point) {
  87. shape.point = vec.toPrecision(point)
  88. return this
  89. },
  90. transform(shape, bounds, { initialShape, transformOrigin, scaleX, scaleY }) {
  91. shape.radius =
  92. initialShape.radius * Math.min(Math.abs(scaleX), Math.abs(scaleY))
  93. shape.point = [
  94. bounds.minX +
  95. (bounds.width - shape.radius * 2) *
  96. (scaleX < 0 ? 1 - transformOrigin[0] : transformOrigin[0]),
  97. bounds.minY +
  98. (bounds.height - shape.radius * 2) *
  99. (scaleY < 0 ? 1 - transformOrigin[1] : transformOrigin[1]),
  100. ]
  101. return this
  102. },
  103. transformSingle(shape, bounds, info) {
  104. shape.radius = Math.min(bounds.width, bounds.height) / 2
  105. shape.point = [bounds.minX, bounds.minY]
  106. return this
  107. },
  108. setParent(shape, parentId) {
  109. shape.parentId = parentId
  110. return this
  111. },
  112. setChildIndex(shape, childIndex) {
  113. shape.childIndex = childIndex
  114. return this
  115. },
  116. canTransform: true,
  117. canChangeAspectRatio: false,
  118. })
  119. export default circle