You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bounding-box.tsx 2.6KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import * as React from 'react'
  2. import { Edge, Corner } from 'types'
  3. import { useSelector } from 'state'
  4. import {
  5. deepCompareArrays,
  6. getBoundsCenter,
  7. getCurrentCamera,
  8. getPage,
  9. getSelectedIds,
  10. getSelectedShapes,
  11. isMobile,
  12. } from 'utils/utils'
  13. import CenterHandle from './center-handle'
  14. import CornerHandle from './corner-handle'
  15. import EdgeHandle from './edge-handle'
  16. import RotateHandle from './rotate-handle'
  17. import Handles from './handles'
  18. export default function Bounds() {
  19. const isBrushing = useSelector((s) => s.isIn('brushSelecting'))
  20. const isSelecting = useSelector((s) => s.isIn('selecting'))
  21. const zoom = useSelector((s) => getCurrentCamera(s.data).zoom)
  22. const bounds = useSelector((s) => s.values.selectedBounds)
  23. const selectedIds = useSelector(
  24. (s) => Array.from(s.values.selectedIds.values()),
  25. deepCompareArrays
  26. )
  27. const rotation = useSelector(({ data }) =>
  28. getSelectedIds(data).size === 1 ? getSelectedShapes(data)[0].rotation : 0
  29. )
  30. const isAllLocked = useSelector((s) => {
  31. const page = getPage(s.data)
  32. return selectedIds.every((id) => page.shapes[id]?.isLocked)
  33. })
  34. const isSingleHandles = useSelector((s) => {
  35. const page = getPage(s.data)
  36. return (
  37. selectedIds.length === 1 &&
  38. page.shapes[selectedIds[0]]?.handles !== undefined
  39. )
  40. })
  41. if (!bounds) return null
  42. if (!isSelecting) return null
  43. if (isSingleHandles) return null
  44. const size = (isMobile().any ? 10 : 8) / zoom // Touch target size
  45. const center = getBoundsCenter(bounds)
  46. return (
  47. <g
  48. pointerEvents={isBrushing ? 'none' : 'all'}
  49. transform={`
  50. rotate(${rotation * (180 / Math.PI)},${center})
  51. translate(${bounds.minX},${bounds.minY})
  52. rotate(${(bounds.rotation || 0) * (180 / Math.PI)}, 0, 0)`}
  53. >
  54. <CenterHandle bounds={bounds} isLocked={isAllLocked} />
  55. {!isAllLocked && (
  56. <>
  57. <EdgeHandle size={size} bounds={bounds} edge={Edge.Top} />
  58. <EdgeHandle size={size} bounds={bounds} edge={Edge.Right} />
  59. <EdgeHandle size={size} bounds={bounds} edge={Edge.Bottom} />
  60. <EdgeHandle size={size} bounds={bounds} edge={Edge.Left} />
  61. <CornerHandle size={size} bounds={bounds} corner={Corner.TopLeft} />
  62. <CornerHandle size={size} bounds={bounds} corner={Corner.TopRight} />
  63. <CornerHandle
  64. size={size}
  65. bounds={bounds}
  66. corner={Corner.BottomRight}
  67. />
  68. <CornerHandle
  69. size={size}
  70. bounds={bounds}
  71. corner={Corner.BottomLeft}
  72. />
  73. <RotateHandle size={size} bounds={bounds} />
  74. </>
  75. )}
  76. </g>
  77. )
  78. }