Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

canvas.tsx 2.5KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import styled from 'styles'
  2. import state, { useSelector } from 'state'
  3. import inputs from 'state/inputs'
  4. import React, { useCallback, useRef } from 'react'
  5. import useZoomEvents from 'hooks/useZoomEvents'
  6. import useCamera from 'hooks/useCamera'
  7. import Defs from './defs'
  8. import Page from './page'
  9. import Brush from './brush'
  10. import Bounds from './bounds/bounding-box'
  11. import BoundsBg from './bounds/bounds-bg'
  12. import Selected from './selected'
  13. import Handles from './bounds/handles'
  14. import { isMobile, throttle } from 'utils/utils'
  15. export default function Canvas() {
  16. const rCanvas = useRef<SVGSVGElement>(null)
  17. const rGroup = useRef<SVGGElement>(null)
  18. useCamera(rGroup)
  19. useZoomEvents()
  20. const isReady = useSelector((s) => s.isIn('ready'))
  21. const handlePointerDown = useCallback((e: React.PointerEvent) => {
  22. if (!inputs.canAccept(e.pointerId)) return
  23. rCanvas.current.setPointerCapture(e.pointerId)
  24. state.send('POINTED_CANVAS', inputs.pointerDown(e, 'canvas'))
  25. }, [])
  26. const handleTouchStart = useCallback((e: React.TouchEvent) => {
  27. if (e.touches.length === 2) {
  28. state.send('TOUCH_UNDO')
  29. } else {
  30. if (isMobile()) {
  31. state.send('TOUCHED_CANVAS')
  32. }
  33. }
  34. }, [])
  35. const handlePointerMove = useCallback((e: React.PointerEvent) => {
  36. if (!inputs.canAccept(e.pointerId)) return
  37. throttledPointerMove(inputs.pointerMove(e))
  38. }, [])
  39. const handlePointerUp = useCallback((e: React.PointerEvent) => {
  40. if (!inputs.canAccept(e.pointerId)) return
  41. rCanvas.current.releasePointerCapture(e.pointerId)
  42. state.send('STOPPED_POINTING', { id: 'canvas', ...inputs.pointerUp(e) })
  43. }, [])
  44. return (
  45. <MainSVG
  46. ref={rCanvas}
  47. onPointerDown={handlePointerDown}
  48. onPointerMove={handlePointerMove}
  49. onPointerUp={handlePointerUp}
  50. onTouchStart={handleTouchStart}
  51. >
  52. <Defs />
  53. {isReady && (
  54. <g ref={rGroup}>
  55. <BoundsBg />
  56. <Page />
  57. <Selected />
  58. <Bounds />
  59. <Handles />
  60. <Brush />
  61. </g>
  62. )}
  63. </MainSVG>
  64. )
  65. }
  66. const MainSVG = styled('svg', {
  67. position: 'fixed',
  68. top: 0,
  69. left: 0,
  70. width: '100%',
  71. height: '100%',
  72. touchAction: 'none',
  73. zIndex: 100,
  74. backgroundColor: '$canvas',
  75. pointerEvents: 'all',
  76. '& *': {
  77. userSelect: 'none',
  78. },
  79. })
  80. // const throttledPointerMove = throttle((payload: any) => {
  81. // state.send('MOVED_POINTER', payload)
  82. // }, 16)
  83. const throttledPointerMove = (payload: any) => {
  84. state.send('MOVED_POINTER', payload)
  85. }