Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

handles.tsx 1.9KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import useHandleEvents from 'hooks/useHandleEvents'
  2. import { getShapeUtils } from 'lib/shape-utils'
  3. import { useRef } from 'react'
  4. import { useSelector } from 'state'
  5. import styled from 'styles'
  6. import { deepCompareArrays, getPage } from 'utils/utils'
  7. import * as vec from 'utils/vec'
  8. export default function Handles() {
  9. const selectedIds = useSelector(
  10. (s) => Array.from(s.values.selectedIds.values()),
  11. deepCompareArrays
  12. )
  13. const shape = useSelector(
  14. ({ data }) =>
  15. selectedIds.length === 1 && getPage(data).shapes[selectedIds[0]]
  16. )
  17. const isSelecting = useSelector((s) =>
  18. s.isInAny('notPointing', 'pinching', 'translatingHandles')
  19. )
  20. if (!shape.handles || !isSelecting) return null
  21. return (
  22. <g>
  23. {Object.values(shape.handles).map((handle) => (
  24. <Handle
  25. key={handle.id}
  26. shapeId={shape.id}
  27. id={handle.id}
  28. point={vec.add(handle.point, shape.point)}
  29. />
  30. ))}
  31. </g>
  32. )
  33. }
  34. function Handle({
  35. shapeId,
  36. id,
  37. point,
  38. }: {
  39. shapeId: string
  40. id: string
  41. point: number[]
  42. }) {
  43. const rGroup = useRef<SVGGElement>(null)
  44. const events = useHandleEvents(id, rGroup)
  45. return (
  46. <StyledGroup
  47. key={id}
  48. className="handles"
  49. ref={rGroup}
  50. {...events}
  51. pointerEvents="all"
  52. transform={`translate(${point})`}
  53. >
  54. <HandleCircleOuter r={12} />
  55. <use href="#handle" pointerEvents="none" />
  56. </StyledGroup>
  57. )
  58. }
  59. const StyledGroup = styled('g', {
  60. '&:hover': {
  61. cursor: 'pointer',
  62. },
  63. '&:active': {
  64. cursor: 'none',
  65. },
  66. })
  67. const HandleCircleOuter = styled('circle', {
  68. fill: 'transparent',
  69. stroke: 'none',
  70. opacity: 0.2,
  71. pointerEvents: 'all',
  72. cursor: 'pointer',
  73. transform: 'scale(var(--scale))',
  74. '&:hover': {
  75. fill: '$selected',
  76. '& > *': {
  77. stroke: '$selected',
  78. },
  79. },
  80. '&:active': {
  81. fill: '$selected',
  82. },
  83. })