Skip to content

Commit

Permalink
refactor(whiteboard): using canvas to render the whiteboard grid dots
Browse files Browse the repository at this point in the history
  • Loading branch information
pengx17 committed Nov 17, 2022
1 parent 8bf59a5 commit 0260f5d
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 51 deletions.
10 changes: 10 additions & 0 deletions tldraw/apps/tldraw-logseq/src/components/Devtools/Devtools.tsx
Expand Up @@ -84,6 +84,15 @@ export const DevTools = observer(() => {
.map(p => p.join(''))
.join('|')

const originPoint = canvasAnchorRef.current
? ReactDOM.createPortal(
<svg className="tl-renderer-dev-tools tl-grid">
<circle cx={point[0] * zoom} cy={point[1] * zoom} r="4" fill="red" />
</svg>,
canvasAnchorRef.current
)
: null

const rendererStatus = statusbarAnchorRef.current
? ReactDOM.createPortal(
<div
Expand All @@ -101,6 +110,7 @@ export const DevTools = observer(() => {

return (
<>
{originPoint}
{rendererStatus}
<HistoryStack />
</>
Expand Down
24 changes: 1 addition & 23 deletions tldraw/apps/tldraw-logseq/src/components/StatusBar/StatusBar.tsx
@@ -1,33 +1,11 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
/* eslint-disable @typescript-eslint/no-explicit-any */
import * as React from 'react'
import { observer } from 'mobx-react-lite'
import { useApp } from '@tldraw/react'
import { observer } from 'mobx-react-lite'
import type { Shape } from '../../lib'

export const StatusBar = observer(function StatusBar() {
const app = useApp<Shape>()
React.useEffect(() => {
const canvas = document.querySelector<HTMLElement>('.logseq-tldraw-wrapper .tl-canvas')
const actionBar = document.querySelector<HTMLElement>('.logseq-tldraw-wrapper .tl-action-bar')
if (canvas) {
canvas.style.height = 'calc(100% - 32px)'
}

if (actionBar) {
actionBar.style.marginBottom = '32px'
}

return () => {
if (canvas) {
canvas.style.height = '100%'
}

if (actionBar) {
actionBar.style.marginBottom = '0px'
}
}
})
return (
<div className="tl-statusbar">
{app.selectedTool.id} | {app.selectedTool.currentState.id}
Expand Down
2 changes: 1 addition & 1 deletion tldraw/packages/core/src/lib/TLSettings.ts
Expand Up @@ -13,7 +13,7 @@ export class TLSettings implements TLSettingsProps {
}

@observable mode: 'dark' | 'light' = 'light'
@observable showGrid = !isSafari()
@observable showGrid = true

@action update(props: Partial<TLSettingsProps>): void {
Object.assign(this, props)
Expand Down
1 change: 1 addition & 0 deletions tldraw/packages/react/package.json
Expand Up @@ -41,6 +41,7 @@
"mobx": "^6.6.2",
"mobx-react-lite": "^3.4.0",
"mousetrap": "^1.6.5",
"polished": "^4.2.2",
"rbush": "^3.0.1",
"uuid": "^8.0.0"
},
Expand Down
100 changes: 74 additions & 26 deletions tldraw/packages/react/src/components/ui/Grid/Grid.tsx
@@ -1,5 +1,7 @@
import { modulate } 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'

Expand All @@ -15,35 +17,81 @@ export const Grid = observer(function Grid({ size }: TLGridProps) {
const {
viewport: {
camera: { point, zoom },
bounds,
},
} = useRendererContext()
return (
<svg className="tl-grid" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
{STEPS.map(([min, mid, _size], i) => {
const s = _size * size * zoom

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
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

return (
<pattern
key={`grid-pattern-${i}`}
id={`grid-${i}`}
width={s}
height={s}
patternUnits="userSpaceOnUse"
>
<circle className={`tl-grid-dot`} cx={gxo} cy={gyo} r={1.5} opacity={opacity} />
</pattern>
)
})}
</defs>
{STEPS.map((_, i) => (
<rect key={`grid-rect-${i}`} width="100%" height="100%" fill={`url(#grid-${i})`} />
))}
</svg>

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" />
)
})
7 changes: 7 additions & 0 deletions tldraw/packages/react/src/hooks/useStylesheet.ts
Expand Up @@ -421,6 +421,13 @@ const tlcss = css`
color: var(--tl-background);
}
.tl-grid-canvas {
position: absolute;
touch-action: none;
pointer-events: none;
user-select: none;
}
.tl-grid {
position: absolute;
width: 100%;
Expand Down
2 changes: 1 addition & 1 deletion tldraw/yarn.lock
Expand Up @@ -3669,7 +3669,7 @@ pirates@^4.0.1:
resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b"
integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==

polished@^4.0.0:
polished@^4.0.0, polished@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/polished/-/polished-4.2.2.tgz#2529bb7c3198945373c52e34618c8fe7b1aa84d1"
integrity sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ==
Expand Down

0 comments on commit 0260f5d

Please sign in to comment.