POC: highlight center on hover

This commit is contained in:
dwelle
2025-09-13 15:41:17 +02:00
parent ef2bde0d03
commit b789308798
4 changed files with 33 additions and 3 deletions

View File

@@ -2072,6 +2072,7 @@ class App extends React.Component<AppProps, AppState> {
/>
)}
<InteractiveCanvas
app={this}
containerRef={this.excalidrawContainerRef}
canvas={this.interactiveCanvas}
elementsMap={elementsMap}

View File

@@ -20,7 +20,12 @@ import type {
RenderableElementsMap,
RenderInteractiveSceneCallback,
} from "../../scene/types";
import type { AppState, Device, InteractiveCanvasAppState } from "../../types";
import type {
AppClassProperties,
AppState,
Device,
InteractiveCanvasAppState,
} from "../../types";
import type { DOMAttributes } from "react";
type InteractiveCanvasProps = {
@@ -36,6 +41,7 @@ type InteractiveCanvasProps = {
appState: InteractiveCanvasAppState;
renderScrollbars: boolean;
device: Device;
app: AppClassProperties;
renderInteractiveSceneCallback: (
data: RenderInteractiveSceneCallback,
) => void;
@@ -145,6 +151,8 @@ const InteractiveCanvas = (props: InteractiveCanvasProps) => {
remotePointerUserStates,
selectionColor,
renderScrollbars: props.renderScrollbars,
// NOTE not memoized on so we don't rerender on cursor move
lastViewportPosition: props.app.lastViewportPosition,
},
device: props.device,
callback: props.renderInteractiveSceneCallback,

View File

@@ -1,4 +1,5 @@
import {
pointDistance,
pointFrom,
pointsEqual,
type GlobalPoint,
@@ -14,6 +15,7 @@ import {
invariant,
THEME,
throttleRAF,
viewportCoordsToSceneCoords,
} from "@excalidraw/common";
import {
@@ -192,6 +194,7 @@ const renderBindingHighlightForBindableElement = (
elementsMap: RenderableElementsMap,
allElementsMap: NonDeletedSceneElementsMap,
appState: InteractiveCanvasAppState,
renderConfig: InteractiveCanvasRenderConfig,
) => {
switch (element.type) {
case "magicframe":
@@ -337,16 +340,32 @@ const renderBindingHighlightForBindableElement = (
break;
}
const { x: cursorX, y: cursorY } = viewportCoordsToSceneCoords(
{
clientX: renderConfig.lastViewportPosition.x,
clientY: renderConfig.lastViewportPosition.y,
},
appState,
);
// Draw center snap area
context.save();
context.translate(element.x + appState.scrollX, element.y + appState.scrollY);
context.strokeStyle = "rgba(0, 0, 0, 0.1)";
context.strokeStyle = "rgba(0, 0, 0, 0.2)";
context.lineWidth = 1 / appState.zoom.value;
context.setLineDash([4 / appState.zoom.value, 4 / appState.zoom.value]);
context.lineDashOffset = 0;
context.fillStyle = "rgba(0, 0, 0, 0.01)";
const radius = 0.5 * (Math.min(element.width, element.height) / 2);
const centerX = element.x + element.width / 2;
const centerY = element.y + element.height / 2;
const isInsideEllipse =
pointDistance(pointFrom(cursorX, cursorY), pointFrom(centerX, centerY)) <=
radius;
context.fillStyle = isInsideEllipse ? "rgba(0, 0, 0, 0.04)" : "transparent";
context.beginPath();
context.ellipse(
element.width / 2,
@@ -899,6 +918,7 @@ const _renderInteractiveScene = ({
elementsMap,
allElementsMap,
appState,
renderConfig,
);
}

View File

@@ -66,6 +66,7 @@ export type InteractiveCanvasRenderConfig = {
remotePointerUsernames: Map<SocketId, string>;
remotePointerButton: Map<SocketId, string | undefined>;
selectionColor: string;
lastViewportPosition: { x: number; y: number };
// extra options passed to the renderer
// ---------------------------------------------------------------------------
renderScrollbars?: boolean;