您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

bounding-box.tsx 2.6KB

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