Improves window resizing, adds shouldRender to shapes

This commit is contained in:
Steve Ruiz 2021-06-27 13:28:54 +01:00
parent ec7ec06a6d
commit 14902099f9
12 changed files with 72 additions and 25 deletions

View file

@ -12,7 +12,6 @@ import BoundsBg from './bounds/bounds-bg'
import Handles from './bounds/handles'
import useCanvasEvents from 'hooks/useCanvasEvents'
import ContextMenu from './context-menu/context-menu'
import useWindowResize from 'hooks/useWindowResize'
export default function Canvas(): JSX.Element {
const rCanvas = useRef<SVGSVGElement>(null)
@ -22,8 +21,6 @@ export default function Canvas(): JSX.Element {
useZoomEvents()
useWindowResize()
const events = useCanvasEvents(rCanvas)
const isReady = useSelector((s) => s.isIn('ready'))

View file

@ -1,20 +1,33 @@
import { useSelector } from 'state'
import { useEffect } from 'react'
import state, { useSelector } from 'state'
import { getShapeUtils } from 'state/shape-utils'
import { PageState, Bounds } from 'types'
import {
boundsCollide,
boundsContain,
debounce,
deepCompareArrays,
getPage,
getPageState,
getViewport,
} from 'utils'
const viewportCache = new WeakMap<PageState, Bounds>()
export default function usePageShapes(): string[] {
// Reset the viewport cache when the window resizes
useEffect(() => {
const handleResize = debounce(() => state.send('RESIZED_WINDOW'), 32)
window.addEventListener('resize', handleResize)
return () => {
window.removeEventListener('resize', handleResize)
}
}, [])
// Get the shapes that fit into the current window
return useSelector((s) => {
const page = getPage(s.data)
const pageState = s.data.pageStates[page.id]
const pageState = getPageState(s.data)
if (!viewportCache.has(pageState)) {
const viewport = getViewport(s.data)

View file

@ -1,15 +0,0 @@
import { useEffect } from 'react'
import state from 'state'
export default function useWindowResize(): void {
useEffect(() => {
function handleResize() {
state.send('RESIZED_WINDOW')
}
window.addEventListener('resize', handleResize)
return () => {
window.removeEventListener('resize', handleResize)
}
}, [])
}

View file

@ -88,6 +88,10 @@ const arrow = registerShapeUtils<ArrowShape>({
}
},
shouldRender(shape, prev) {
return shape.handles !== prev.handles || shape.style !== prev.style
},
render(shape) {
const { id, bend, handles, style } = shape
const { start, end, bend: _bend } = handles

View file

@ -42,6 +42,14 @@ const ellipse = registerShapeUtils<EllipseShape>({
}
},
shouldRender(shape, prev) {
return (
shape.radiusY !== prev.radiusY ||
shape.radiusX !== prev.radiusX ||
shape.style !== prev.style
)
},
render(shape) {
const { id, radiusX, radiusY, style } = shape
const styles = getShapeStyle(style)

View file

@ -34,6 +34,10 @@ const line = registerShapeUtils<LineShape>({
}
},
shouldRender(shape, prev) {
return shape.direction !== prev.direction || shape.style !== prev.style
},
render({ id, direction }) {
const [x1, y1] = vec.add([0, 0], vec.mul(direction, 10000))
const [x2, y2] = vec.sub([0, 0], vec.mul(direction, 10000))

View file

@ -33,6 +33,9 @@ const polyline = registerShapeUtils<PolylineShape>({
}
},
shouldRender(shape, prev) {
return shape.points !== prev.points || shape.style !== prev.style
},
render({ id, points }) {
return <polyline id={id} points={points.toString()} />
},

View file

@ -34,6 +34,9 @@ const ray = registerShapeUtils<RayShape>({
}
},
shouldRender(shape, prev) {
return shape.direction !== prev.direction || shape.style !== prev.style
},
render({ id, direction }) {
const [x2, y2] = vec.add([0, 0], vec.mul(direction, 10000))

View file

@ -33,6 +33,10 @@ const rectangle = registerShapeUtils<RectangleShape>({
}
},
shouldRender(shape, prev) {
return shape.size !== prev.size || shape.style !== prev.style
},
render(shape) {
const { id, size, radius, style } = shape
const styles = getShapeStyle(style)

View file

@ -70,6 +70,14 @@ const text = registerShapeUtils<TextShape>({
}
},
shouldRender(shape, prev) {
return (
shape.text !== prev.text ||
shape.scale !== prev.scale ||
shape.style !== prev.style
)
},
render(shape, { isEditing, ref }) {
const { id, text, style } = shape
const styles = getShapeStyle(style)

View file

@ -173,7 +173,7 @@ const state = createState({
else: ['zoomCameraToActual'],
},
on: {
RESIZED_WINDW: 'updateOnResize',
RESIZED_WINDOW: 'resetPageState',
RESET_PAGE: 'resetPage',
TOGGLED_READ_ONLY: 'toggleReadOnly',
LOADED_FONTS: 'resetShapes',
@ -1124,8 +1124,11 @@ const state = createState({
},
},
actions: {
updateOnResize(data) {
getPageState(data).camera.point = { ...getPageState(data).camera.point }
resetPageState(data) {
// getPageState(data).camera.point = { ...getPageState(data).camera.point }
const pageState = data.pageStates[data.currentPageId]
data.pageStates[data.currentPageId] = { ...pageState }
},
toggleReadOnly(data) {

View file

@ -1716,6 +1716,21 @@ export function getSvgPathFromStroke(stroke: number[][]): string {
return d.join(' ')
}
export function debounce<T extends (...args: unknown[]) => unknown>(
callback: T,
waitFor: number
): (...args: Parameters<T>) => ReturnType<T> {
let timeout: ReturnType<typeof setTimeout>
return (...args: Parameters<T>): ReturnType<T> => {
let result: any
timeout && clearTimeout(timeout)
timeout = setTimeout(() => {
result = callback(...args)
}, waitFor)
return result
}
}
/**
* Get a precise point from an event.
* @param e