Improves window resizing, adds shouldRender to shapes
This commit is contained in:
parent
ec7ec06a6d
commit
14902099f9
12 changed files with 72 additions and 25 deletions
|
@ -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'))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}, [])
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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()} />
|
||||
},
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue