mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
feat: in canvas links between shapes (#8812)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
This commit is contained in:
parent
a758aaf8f6
commit
c0b80a03bd
32 changed files with 1281 additions and 217 deletions
|
@ -40,6 +40,7 @@ import type {
|
|||
import { getDefaultAppState } from "../appState";
|
||||
import {
|
||||
BOUND_TEXT_PADDING,
|
||||
DEFAULT_REDUCED_GLOBAL_ALPHA,
|
||||
ELEMENT_READY_TO_ERASE_OPACITY,
|
||||
FRAME_STYLE,
|
||||
MIME_TYPES,
|
||||
|
@ -109,10 +110,13 @@ export const getRenderOpacity = (
|
|||
containingFrame: ExcalidrawFrameLikeElement | null,
|
||||
elementsPendingErasure: ElementsPendingErasure,
|
||||
pendingNodes: Readonly<PendingExcalidrawElements> | null,
|
||||
globalAlpha: number = 1,
|
||||
) => {
|
||||
// multiplying frame opacity with element opacity to combine them
|
||||
// (e.g. frame 50% and element 50% opacity should result in 25% opacity)
|
||||
let opacity = ((containingFrame?.opacity ?? 100) * element.opacity) / 10000;
|
||||
let opacity =
|
||||
(((containingFrame?.opacity ?? 100) * element.opacity) / 10000) *
|
||||
globalAlpha;
|
||||
|
||||
// if pending erasure, multiply again to combine further
|
||||
// (so that erasing always results in lower opacity than original)
|
||||
|
@ -700,11 +704,17 @@ export const renderElement = (
|
|||
renderConfig: StaticCanvasRenderConfig,
|
||||
appState: StaticCanvasAppState,
|
||||
) => {
|
||||
const reduceAlphaForSelection =
|
||||
appState.openDialog?.name === "elementLinkSelector" &&
|
||||
!appState.selectedElementIds[element.id] &&
|
||||
!appState.hoveredElementIds[element.id];
|
||||
|
||||
context.globalAlpha = getRenderOpacity(
|
||||
element,
|
||||
getContainingFrame(element, elementsMap),
|
||||
renderConfig.elementsPendingErasure,
|
||||
renderConfig.pendingFlowchartNodes,
|
||||
reduceAlphaForSelection ? DEFAULT_REDUCED_GLOBAL_ALPHA : 1,
|
||||
);
|
||||
|
||||
switch (element.type) {
|
||||
|
|
|
@ -25,11 +25,13 @@ import type {
|
|||
} from "../scene/types";
|
||||
import {
|
||||
EXTERNAL_LINK_IMG,
|
||||
ELEMENT_LINK_IMG,
|
||||
getLinkHandleFromCoords,
|
||||
} from "../components/hyperlink/helpers";
|
||||
import { bootstrapCanvas, getNormalizedCanvasDimensions } from "./helpers";
|
||||
import { throttleRAF } from "../utils";
|
||||
import { getBoundTextElement } from "../element/textElement";
|
||||
import { isElementLink } from "../element/elementLink";
|
||||
|
||||
const GridLineColor = {
|
||||
Bold: "#dddddd",
|
||||
|
@ -133,7 +135,16 @@ const frameClip = (
|
|||
);
|
||||
};
|
||||
|
||||
let linkCanvasCache: any;
|
||||
type LinkIconCanvas = HTMLCanvasElement & { zoom: number };
|
||||
|
||||
const linkIconCanvasCache: {
|
||||
regularLink: LinkIconCanvas | null;
|
||||
elementLink: LinkIconCanvas | null;
|
||||
} = {
|
||||
regularLink: null,
|
||||
elementLink: null,
|
||||
};
|
||||
|
||||
const renderLinkIcon = (
|
||||
element: NonDeletedExcalidrawElement,
|
||||
context: CanvasRenderingContext2D,
|
||||
|
@ -153,38 +164,44 @@ const renderLinkIcon = (
|
|||
context.translate(appState.scrollX + centerX, appState.scrollY + centerY);
|
||||
context.rotate(element.angle);
|
||||
|
||||
if (!linkCanvasCache || linkCanvasCache.zoom !== appState.zoom.value) {
|
||||
linkCanvasCache = document.createElement("canvas");
|
||||
linkCanvasCache.zoom = appState.zoom.value;
|
||||
linkCanvasCache.width =
|
||||
width * window.devicePixelRatio * appState.zoom.value;
|
||||
linkCanvasCache.height =
|
||||
const canvasKey = isElementLink(element.link)
|
||||
? "elementLink"
|
||||
: "regularLink";
|
||||
|
||||
let linkCanvas = linkIconCanvasCache[canvasKey];
|
||||
|
||||
if (!linkCanvas || linkCanvas.zoom !== appState.zoom.value) {
|
||||
linkCanvas = Object.assign(document.createElement("canvas"), {
|
||||
zoom: appState.zoom.value,
|
||||
});
|
||||
linkCanvas.width = width * window.devicePixelRatio * appState.zoom.value;
|
||||
linkCanvas.height =
|
||||
height * window.devicePixelRatio * appState.zoom.value;
|
||||
const linkCanvasCacheContext = linkCanvasCache.getContext("2d")!;
|
||||
linkIconCanvasCache[canvasKey] = linkCanvas;
|
||||
|
||||
const linkCanvasCacheContext = linkCanvas.getContext("2d")!;
|
||||
linkCanvasCacheContext.scale(
|
||||
window.devicePixelRatio * appState.zoom.value,
|
||||
window.devicePixelRatio * appState.zoom.value,
|
||||
);
|
||||
linkCanvasCacheContext.fillStyle = "#fff";
|
||||
linkCanvasCacheContext.fillRect(0, 0, width, height);
|
||||
linkCanvasCacheContext.drawImage(EXTERNAL_LINK_IMG, 0, 0, width, height);
|
||||
|
||||
if (canvasKey === "elementLink") {
|
||||
linkCanvasCacheContext.drawImage(ELEMENT_LINK_IMG, 0, 0, width, height);
|
||||
} else {
|
||||
linkCanvasCacheContext.drawImage(
|
||||
EXTERNAL_LINK_IMG,
|
||||
0,
|
||||
0,
|
||||
width,
|
||||
height,
|
||||
);
|
||||
}
|
||||
|
||||
linkCanvasCacheContext.restore();
|
||||
context.drawImage(
|
||||
linkCanvasCache,
|
||||
x - centerX,
|
||||
y - centerY,
|
||||
width,
|
||||
height,
|
||||
);
|
||||
} else {
|
||||
context.drawImage(
|
||||
linkCanvasCache,
|
||||
x - centerX,
|
||||
y - centerY,
|
||||
width,
|
||||
height,
|
||||
);
|
||||
}
|
||||
context.drawImage(linkCanvas, x - centerX, y - centerY, width, height);
|
||||
context.restore();
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue