Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  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. export default function Canvas() {
  14. const rCanvas = useRef<SVGSVGElement>(null)
  15. const rGroup = useRef<SVGGElement>(null)
  16. const events = useZoomEvents(rCanvas)
  17. useCamera(rGroup)
  18. const isReady = useSelector((s) => s.isIn('ready'))
  19. const handlePointerDown = useCallback((e: React.PointerEvent) => {
  20. if (!inputs.canAccept(e.pointerId)) return
  21. rCanvas.current.setPointerCapture(e.pointerId)
  22. state.send('POINTED_CANVAS', inputs.pointerDown(e, 'canvas'))
  23. }, [])
  24. const handleTouchStart = useCallback((e: React.TouchEvent) => {
  25. if (e.touches.length === 2) {
  26. state.send('TOUCH_UNDO')
  27. }
  28. }, [])
  29. const handlePointerMove = useCallback((e: React.PointerEvent) => {
  30. if (!inputs.canAccept(e.pointerId)) return
  31. if (inputs.canAccept(e.pointerId)) {
  32. state.send('MOVED_POINTER', inputs.pointerMove(e))
  33. }
  34. }, [])
  35. const handlePointerUp = useCallback((e: React.PointerEvent) => {
  36. if (!inputs.canAccept(e.pointerId)) return
  37. rCanvas.current.releasePointerCapture(e.pointerId)
  38. state.send('STOPPED_POINTING', { id: 'canvas', ...inputs.pointerUp(e) })
  39. }, [])
  40. return (
  41. <MainSVG
  42. ref={rCanvas}
  43. {...events}
  44. onPointerDown={handlePointerDown}
  45. onPointerMove={handlePointerMove}
  46. onPointerUp={handlePointerUp}
  47. onTouchStart={handleTouchStart}
  48. >
  49. <Defs />
  50. {isReady && (
  51. <g ref={rGroup}>
  52. <BoundsBg />
  53. <Page />
  54. <Selected />
  55. <Bounds />
  56. <Brush />
  57. </g>
  58. )}
  59. </MainSVG>
  60. )
  61. }
  62. const MainSVG = styled('svg', {
  63. position: 'fixed',
  64. top: 0,
  65. left: 0,
  66. width: '100%',
  67. height: '100%',
  68. touchAction: 'none',
  69. zIndex: 100,
  70. '& *': {
  71. userSelect: 'none',
  72. },
  73. })