1
0
Эх сурвалжийг харах

fix: optimize dot grid svg rendering in Safari

Peng Xiao 2 жил өмнө
parent
commit
a72bb8bcb4

+ 7 - 90
tldraw/packages/react/src/components/ui/Grid/Grid.tsx

@@ -1,7 +1,5 @@
-import { isSafari, modulate } from '@tldraw/core'
+import { modulate, clamp } from '@tldraw/core'
 import { observer } from 'mobx-react-lite'
-import { transparentize } from 'polished'
-import React from 'react'
 import { useRendererContext } from '../../../hooks'
 import type { TLGridProps } from '../../../types'
 
@@ -27,7 +25,9 @@ const SVGGrid = observer(function CanvasGrid({ size }: TLGridProps) {
           const yo = point[1] * zoom
           const gxo = xo > 0 ? xo % s : s + (xo % s)
           const gyo = yo > 0 ? yo % s : s + (yo % s)
-          const opacity = zoom < mid ? modulate(zoom, [min, mid], [0, 1]) : 1
+          const opacity = modulate(zoom, [min, mid], [0, 1])
+
+          const hide = opacity > 2 || opacity < 0.1
 
           return (
             <pattern
@@ -37,7 +37,9 @@ const SVGGrid = observer(function CanvasGrid({ size }: TLGridProps) {
               height={s}
               patternUnits="userSpaceOnUse"
             >
-              <circle className={`tl-grid-dot`} cx={gxo} cy={gyo} r={1.5} opacity={opacity} />
+              {!hide && (
+                <circle className={`tl-grid-dot`} cx={gxo} cy={gyo} r={1.5} opacity={clamp(opacity, 0, 1)} />
+              )}
             </pattern>
           )
         })}
@@ -49,91 +51,6 @@ const SVGGrid = observer(function CanvasGrid({ size }: TLGridProps) {
   )
 })
 
-// Grid is slow to render. Maybe we render it using canvas?
-const CanvasGrid = observer(function Grid({ size }: TLGridProps) {
-  const {
-    viewport: {
-      camera: { point, zoom },
-      bounds,
-    },
-  } = useRendererContext()
-
-  const ref = React.useRef<HTMLCanvasElement>(null)
-
-  // Use useEffect will cause the render flickering
-  React.useLayoutEffect(() => {
-    if (ref.current) {
-      const canvas = ref.current
-      if (canvas?.getContext) {
-        const fillColor = getComputedStyle(canvas)
-          .getPropertyValue('--ls-quaternary-background-color')
-          .trim()
-        const ctx = canvas.getContext('2d')
-        if (ctx && fillColor) {
-          const { width, height } = canvas
-          // fill the canvas with dots
-          ctx.clearRect(0, 0, width, height)
-
-          const xo = point[0] * zoom
-          const yo = point[1] * zoom
-
-          STEPS.forEach(([min, mid, _size]) => {
-            const s = _size * size * zoom
-            const gxo = xo > 0 ? xo % s : s + (xo % s)
-            const gyo = yo > 0 ? yo % s : s + (yo % s)
-            const opacity = zoom < mid ? modulate(zoom, [min, mid], [0, 1], true) : 1
-            ctx.fillStyle = transparentize(1 - opacity, fillColor)
-
-            if (opacity < 0.5 || s < 32) return
-            for (let i = gyo; i < height; i += s) {
-              for (let j = gxo; j < width; j += s) {
-                ctx.beginPath()
-                ctx.arc(j, i, 1.5, 0, 2 * Math.PI)
-                ctx.closePath()
-                ctx.fill()
-              }
-            }
-            // Pattern should have better performance, but I cannot make the offset correctly ...
-            // for (let i = 0; i < height; i += _size) {
-            //   const y = i * _size
-            //   for (let j = 0; j < width; j += _size) {
-            //     const x = j * _size
-            //     ctx.fillRect(x, y, _size, _size)
-            //   }
-            // }
-            // const pattern = document.createElement('canvas').getContext('2d')
-            // if (pattern) {
-            //   const s = _size * size * zoom
-            //   if (s < 1) {
-            //     return
-            //   }
-            //   const xo = point[0] * zoom
-            //   const yo = point[1] * zoom
-            //   const gxo = xo > 0 ? xo % s : s + (xo % s)
-            //   const gyo = yo > 0 ? yo % s : s + (yo % s)
-            //   const opacity = zoom < mid ? modulate(zoom, [min, mid], [0, 1]) : 1
-            //   pattern.canvas.width = s
-            //   pattern.canvas.height = s
-            //   pattern.beginPath()
-            //   pattern.arc(gxo, gyo, 1.5, 0, 2 * Math.PI)
-            //   pattern.fillStyle = transparentize(1 - opacity, fillColor)
-            //   pattern.fill()
-            //   pattern.closePath()
-            //   ctx.fillStyle = ctx.createPattern(pattern.canvas, 'repeat')!
-            //   ctx.fillRect(0, 0, width, height)
-            // }
-          })
-        }
-      }
-    }
-  }, [point[0], point[1], zoom, bounds.width, bounds.height])
-
-  return <canvas ref={ref} width={bounds.width} height={bounds.height} className="tl-grid-canvas" />
-})
-
 export const Grid = observer(function Grid({ size }: TLGridProps) {
-  if (isSafari()) {
-    return <CanvasGrid size={size} />
-  }
   return <SVGGrid size={size} />
 })

+ 1 - 1
tldraw/packages/react/src/hooks/useGestureEvents.ts

@@ -24,7 +24,7 @@ export function useGestureEvents(ref: React.RefObject<HTMLDivElement>) {
 
       const [x, y, z] = normalizeWheel(event)
 
-      if (inputs.state === 'pinching' || rWheelTs.current === event.timeStamp) {
+      if (inputs.state === 'pinching' || rWheelTs.current >= event.timeStamp) {
         return
       }