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.

bounds-bg.tsx 2.2KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import { useCallback, useRef } from 'react'
  2. import state, { useSelector } from 'state'
  3. import inputs from 'state/inputs'
  4. import styled from 'styles'
  5. import { deepCompareArrays, getPage } from 'utils/utils'
  6. function handlePointerDown(e: React.PointerEvent<SVGRectElement>) {
  7. if (e.buttons !== 1) return
  8. if (!inputs.canAccept(e.pointerId)) return
  9. e.stopPropagation()
  10. e.currentTarget.setPointerCapture(e.pointerId)
  11. state.send('POINTED_BOUNDS', inputs.pointerDown(e, 'bounds'))
  12. }
  13. function handlePointerUp(e: React.PointerEvent<SVGRectElement>) {
  14. if (e.buttons !== 1) return
  15. if (!inputs.canAccept(e.pointerId)) return
  16. e.stopPropagation()
  17. e.currentTarget.releasePointerCapture(e.pointerId)
  18. state.send('STOPPED_POINTING', inputs.pointerUp(e))
  19. }
  20. export default function BoundsBg() {
  21. const rBounds = useRef<SVGRectElement>(null)
  22. const bounds = useSelector((state) => state.values.selectedBounds)
  23. const isSelecting = useSelector((s) => s.isIn('selecting'))
  24. const selectedIds = useSelector(
  25. (s) => Array.from(s.values.selectedIds.values()),
  26. deepCompareArrays
  27. )
  28. const rotation = useSelector((s) => {
  29. if (selectedIds.length === 1) {
  30. const { shapes } = getPage(s.data)
  31. const selected = Array.from(s.values.selectedIds.values())[0]
  32. return shapes[selected].rotation
  33. } else {
  34. return 0
  35. }
  36. })
  37. const isAllHandles = useSelector((s) => {
  38. const page = getPage(s.data)
  39. const selectedIds = Array.from(s.values.selectedIds.values())
  40. return (
  41. selectedIds.length === 1 &&
  42. page.shapes[selectedIds[0]]?.handles !== undefined
  43. )
  44. })
  45. if (isAllHandles) return null
  46. if (!bounds) return null
  47. if (!isSelecting) return null
  48. const { width, height } = bounds
  49. return (
  50. <StyledBoundsBg
  51. ref={rBounds}
  52. width={Math.max(1, width)}
  53. height={Math.max(1, height)}
  54. transform={`
  55. rotate(${rotation * (180 / Math.PI)},
  56. ${(bounds.minX + bounds.maxX) / 2},
  57. ${(bounds.minY + bounds.maxY) / 2})
  58. translate(${bounds.minX},${bounds.minY})
  59. rotate(${(bounds.rotation || 0) * (180 / Math.PI)}, 0, 0)`}
  60. onPointerDown={handlePointerDown}
  61. onPointerUp={handlePointerUp}
  62. />
  63. )
  64. }
  65. const StyledBoundsBg = styled('rect', {
  66. fill: '$boundsBg',
  67. })