fix(highlight): Overdraw fixes

This commit is contained in:
Mark Tolmacs
2025-08-27 15:59:50 +02:00
parent 571e4119ab
commit 416404dacb
3 changed files with 46 additions and 47 deletions

View File

@@ -602,6 +602,42 @@ const generateElementWithCanvas = (
return prevElementWithCanvas;
};
const drawElementHighlight = (
context: CanvasRenderingContext2D,
appState: StaticCanvasAppState,
) => {
if (appState.suggestedBinding) {
const cx =
(appState.suggestedBinding.x +
appState.suggestedBinding.width / 2 +
appState.scrollX) *
window.devicePixelRatio;
const cy =
(appState.suggestedBinding.y +
appState.suggestedBinding.height / 2 +
appState.scrollY) *
window.devicePixelRatio;
context.save();
context.translate(cx, cy);
context.rotate(appState.suggestedBinding.angle);
context.translate(-cx, -cy);
context.translate(
appState.scrollX + appState.suggestedBinding.x,
appState.scrollY + appState.suggestedBinding.y,
);
context.scale(1 / window.devicePixelRatio, 1 / window.devicePixelRatio);
const drawable = ShapeCache.generateBindableElementHighlight(
appState.suggestedBinding,
appState,
);
rough.canvas(context.canvas).draw(drawable);
context.restore();
}
};
const drawElementFromCanvas = (
elementWithCanvas: ExcalidrawElementWithCanvas,
context: CanvasRenderingContext2D,
@@ -691,6 +727,10 @@ const drawElementFromCanvas = (
context.restore();
// Clear the nested element we appended to the DOM
if (appState.suggestedBinding?.id === elementWithCanvas.element.id) {
drawElementHighlight(context, appState);
}
};
export const renderSelectionElement = (

View File

@@ -113,11 +113,6 @@ export class ShapeCache {
>(
element: T,
appState: Pick<InteractiveCanvasAppState, "theme">,
renderConfig?: {
isExporting: boolean;
canvasBackgroundColor: AppState["viewBackgroundColor"];
embedsValidationStatus: EmbedsValidationStatus;
},
) => {
let shape =
(ShapeCache.get(element) as Drawable | null) ||
@@ -129,12 +124,13 @@ export class ShapeCache {
// Clone the shape from the cache
shape = {
...shape,
options: {
...shape.options,
fill: "transparent",
stroke: appState.theme === THEME.DARK ? "#035da1" : "#6abdfc",
},
};
shape.options.fill = "transparent";
shape.options.stroke =
appState.theme === THEME.DARK ? "#035da1" : "#6abdfc";
return shape;
};

View File

@@ -1,5 +1,3 @@
import rough from "roughjs/bin/rough";
import {
pointFrom,
pointsEqual,
@@ -18,7 +16,7 @@ import {
throttleRAF,
} from "@excalidraw/common";
import { LinearElementEditor, ShapeCache } from "@excalidraw/element";
import { LinearElementEditor } from "@excalidraw/element";
import {
getOmitSidesForDevice,
getTransformHandles,
@@ -249,37 +247,6 @@ const renderSelectionBorder = (
context.restore();
};
const renderBindingHighlight = (
context: CanvasRenderingContext2D,
appState: InteractiveCanvasAppState,
suggestedBinding: NonNullable<InteractiveCanvasAppState["suggestedBinding"]>,
) => {
const cx =
(suggestedBinding.x + suggestedBinding.width / 2 + appState.scrollX) *
window.devicePixelRatio;
const cy =
(suggestedBinding.y + suggestedBinding.height / 2 + appState.scrollY) *
window.devicePixelRatio;
context.save();
context.translate(cx, cy);
context.rotate(suggestedBinding.angle);
context.translate(-cx, -cy);
context.translate(
appState.scrollX + suggestedBinding.x,
appState.scrollY + suggestedBinding.y,
);
context.scale(1 / window.devicePixelRatio, 1 / window.devicePixelRatio);
const drawable = ShapeCache.generateBindableElementHighlight(
suggestedBinding,
appState,
);
rough.canvas(context.canvas).draw(drawable);
context.restore();
};
const renderFrameHighlight = (
context: CanvasRenderingContext2D,
appState: InteractiveCanvasAppState,
@@ -740,10 +707,6 @@ const _renderInteractiveScene = ({
}
}
if (appState.isBindingEnabled && appState.suggestedBinding) {
renderBindingHighlight(context, appState, appState.suggestedBinding);
}
if (appState.frameToHighlight) {
renderFrameHighlight(
context,