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

bounding-box.tsx 2.6KB

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