Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

index.tsx 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import {
  2. Bounds,
  3. BoundsSnapshot,
  4. Shape,
  5. Shapes,
  6. ShapeType,
  7. Corner,
  8. Edge,
  9. ShapeByType,
  10. ShapeStyles,
  11. } from "types"
  12. import circle from "./circle"
  13. import dot from "./dot"
  14. import polyline from "./polyline"
  15. import rectangle from "./rectangle"
  16. import ellipse from "./ellipse"
  17. import line from "./line"
  18. import ray from "./ray"
  19. /*
  20. Shape Utiliies
  21. A shape utility is an object containing utility methods for each type of shape
  22. in the application. While shapes may be very different, each shape must support
  23. a common set of utility methods, such as hit tests or translations, that
  24. Operations throughout the app will call these utility methods
  25. when performing tests (such as hit tests) or mutations, such as translations.
  26. */
  27. export interface ShapeUtility<K extends Readonly<Shape>> {
  28. // A cache for the computed bounds of this kind of shape.
  29. boundsCache: WeakMap<K, Bounds>
  30. // Whether to show transform controls when this shape is selected.
  31. canTransform: boolean
  32. // Whether the shape's aspect ratio can change
  33. canChangeAspectRatio: boolean
  34. // Create a new shape.
  35. create(props: Partial<K>): K
  36. applyStyles(
  37. this: ShapeUtility<K>,
  38. shape: K,
  39. style: ShapeStyles
  40. ): ShapeUtility<K>
  41. // Set the shape's point.
  42. translateTo(this: ShapeUtility<K>, shape: K, delta: number[]): ShapeUtility<K>
  43. // Set the shape's rotation.
  44. rotateTo(this: ShapeUtility<K>, shape: K, rotation: number): ShapeUtility<K>
  45. // Transform to fit a new bounding box when more than one shape is selected.
  46. transform(
  47. this: ShapeUtility<K>,
  48. shape: K,
  49. bounds: Bounds,
  50. info: {
  51. type: Edge | Corner
  52. initialShape: K
  53. scaleX: number
  54. scaleY: number
  55. transformOrigin: number[]
  56. }
  57. ): ShapeUtility<K>
  58. // Transform a single shape to fit a new bounding box.
  59. transformSingle(
  60. this: ShapeUtility<K>,
  61. shape: K,
  62. bounds: Bounds,
  63. info: {
  64. type: Edge | Corner
  65. initialShape: K
  66. scaleX: number
  67. scaleY: number
  68. transformOrigin: number[]
  69. }
  70. ): ShapeUtility<K>
  71. // Move a shape to a new parent.
  72. setParent(this: ShapeUtility<K>, shape: K, parentId: string): ShapeUtility<K>
  73. // Change the child index of a shape
  74. setChildIndex(
  75. this: ShapeUtility<K>,
  76. shape: K,
  77. childIndex: number
  78. ): ShapeUtility<K>
  79. // Render a shape to JSX.
  80. render(this: ShapeUtility<K>, shape: K): JSX.Element
  81. // Get the bounds of the a shape.
  82. getBounds(this: ShapeUtility<K>, shape: K): Bounds
  83. // Get the routated bounds of the a shape.
  84. getRotatedBounds(this: ShapeUtility<K>, shape: K): Bounds
  85. // Get the center of the shape
  86. getCenter(this: ShapeUtility<K>, shape: K): number[]
  87. // Test whether a point lies within a shape.
  88. hitTest(this: ShapeUtility<K>, shape: K, test: number[]): boolean
  89. // Test whether bounds collide with or contain a shape.
  90. hitTestBounds(this: ShapeUtility<K>, shape: K, bounds: Bounds): boolean
  91. }
  92. // A mapping of shape types to shape utilities.
  93. const shapeUtilityMap: Record<ShapeType, ShapeUtility<Shape>> = {
  94. [ShapeType.Circle]: circle,
  95. [ShapeType.Dot]: dot,
  96. [ShapeType.Polyline]: polyline,
  97. [ShapeType.Rectangle]: rectangle,
  98. [ShapeType.Ellipse]: ellipse,
  99. [ShapeType.Line]: line,
  100. [ShapeType.Ray]: ray,
  101. }
  102. /**
  103. * A helper to retrieve a shape utility based on a shape object.
  104. * @param shape
  105. * @returns
  106. */
  107. export function getShapeUtils<T extends Shape>(shape: T): ShapeUtility<T> {
  108. return shapeUtilityMap[shape.type] as ShapeUtility<T>
  109. }
  110. /**
  111. * A factory of shape utilities, with typing enforced.
  112. * @param shape
  113. * @returns
  114. */
  115. export function registerShapeUtils<T extends Shape>(
  116. shape: ShapeUtility<T>
  117. ): ShapeUtility<T> {
  118. return Object.freeze(shape)
  119. }
  120. export function createShape<T extends Shape>(
  121. type: T["type"],
  122. props: Partial<T>
  123. ) {
  124. return shapeUtilityMap[type].create(props) as T
  125. }
  126. export default shapeUtilityMap