From 345e3f68f168c93599653e83c1f7eea28659790f Mon Sep 17 00:00:00 2001 From: Mark Tolmacs Date: Tue, 16 Sep 2025 20:35:17 +0200 Subject: [PATCH] chore:Basic interactive canvas animation re-render trigger for highlights Signed-off-by: Mark Tolmacs --- .../excalidraw/actions/actionFinalize.tsx | 2 +- packages/excalidraw/components/App.tsx | 2 +- .../components/canvases/InteractiveCanvas.tsx | 50 +++++++++++++++++++ packages/excalidraw/types.ts | 2 + 4 files changed, 54 insertions(+), 2 deletions(-) diff --git a/packages/excalidraw/actions/actionFinalize.tsx b/packages/excalidraw/actions/actionFinalize.tsx index 9e2b10e167..64373d08ed 100644 --- a/packages/excalidraw/actions/actionFinalize.tsx +++ b/packages/excalidraw/actions/actionFinalize.tsx @@ -135,7 +135,7 @@ export const actionFinalize = register({ } const activeToolLocked = appState.activeTool?.locked; - console.log("finalize - activeToolLocked:", activeToolLocked); + return { elements: element.points.length < 2 || isInvisiblySmallElement(element) diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index f1eff1d19a..c6b47078e7 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -619,7 +619,7 @@ class App extends React.Component { public flowChartCreator: FlowChartCreator = new FlowChartCreator(); private flowChartNavigator: FlowChartNavigator = new FlowChartNavigator(); - private bindModeHandler: ReturnType | null = null; + bindModeHandler: ReturnType | null = null; hitLinkElement?: NonDeletedExcalidrawElement; lastPointerDownEvent: React.PointerEvent | null = null; diff --git a/packages/excalidraw/components/canvases/InteractiveCanvas.tsx b/packages/excalidraw/components/canvases/InteractiveCanvas.tsx index efca26e4c6..b315b32e08 100644 --- a/packages/excalidraw/components/canvases/InteractiveCanvas.tsx +++ b/packages/excalidraw/components/canvases/InteractiveCanvas.tsx @@ -1,12 +1,14 @@ import React, { useEffect, useRef } from "react"; import { + BIND_MODE_TIMEOUT, CURSOR_TYPE, isShallowEqual, sceneCoordsToViewportCoords, } from "@excalidraw/common"; import type { + ExcalidrawBindableElement, NonDeletedExcalidrawElement, NonDeletedSceneElementsMap, } from "@excalidraw/element/types"; @@ -79,6 +81,54 @@ type InteractiveCanvasProps = { const InteractiveCanvas = (props: InteractiveCanvasProps) => { const isComponentMounted = useRef(false); + // START - Binding highlight timeout animation + const currentSuggestedBinding = useRef( + null, + ); + const animationInterval = useRef(null); + const [animationFrameCount, triggerAnnimationRerender] = React.useState(0); + + if (props.app.state.suggestedBinding === null && animationInterval.current) { + clearInterval(animationInterval.current); + animationInterval.current = null; + triggerAnnimationRerender(0); + } + + if (currentSuggestedBinding.current !== props.appState.suggestedBinding) { + if (animationInterval.current !== null) { + currentSuggestedBinding.current = props.appState.suggestedBinding; + clearInterval(animationInterval.current); + animationInterval.current = null; + triggerAnnimationRerender(0); + } + } + + if ( + animationFrameCount > BIND_MODE_TIMEOUT / 10 && + animationInterval.current + ) { + clearInterval(animationInterval.current); + animationInterval.current = null; + triggerAnnimationRerender(0); + } else if ( + props.app.state.bindMode === "orbit" && + props.app.bindModeHandler // Timeout is running + ) { + if (animationInterval.current === null) { + animationInterval.current = setInterval(() => { + triggerAnnimationRerender((count) => count + 1); + }, 1000 / 60 /* 60 FPS animation */); + } + } else { + // eslint-disable-next-line no-lonely-if + if (animationInterval.current) { + clearInterval(animationInterval.current); + animationInterval.current = null; + triggerAnnimationRerender(0); + } + } + // END - Binding highlight timeout animation + useEffect(() => { if (!isComponentMounted.current) { isComponentMounted.current = true; diff --git a/packages/excalidraw/types.ts b/packages/excalidraw/types.ts index de2e79aeb7..d16dd87960 100644 --- a/packages/excalidraw/types.ts +++ b/packages/excalidraw/types.ts @@ -747,6 +747,8 @@ export type AppClassProperties = { updateEditorAtom: App["updateEditorAtom"]; defaultSelectionTool: "selection" | "lasso"; + + bindModeHandler: App["bindModeHandler"]; }; export type PointerDownState = Readonly<{