mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-04-14 16:40:58 -04:00
* [WIP] Add names next to pointers This implements the rendering and messaging across. Still need to do the UI to set the name. Also, not really sure what's the best place to send the name and store it. * Add randomized names Co-authored-by: Christopher Chedeau <vjeux@fb.com>
119 lines
3.3 KiB
TypeScript
119 lines
3.3 KiB
TypeScript
import rough from "roughjs/bin/rough";
|
|
import { ExcalidrawElement } from "../element/types";
|
|
import { getCommonBounds } from "../element/bounds";
|
|
import { renderScene, renderSceneToSvg } from "../renderer/renderScene";
|
|
import { distance, SVG_NS } from "../utils";
|
|
import { normalizeScroll } from "./scroll";
|
|
import { AppState } from "../types";
|
|
|
|
export function exportToCanvas(
|
|
elements: readonly ExcalidrawElement[],
|
|
appState: AppState,
|
|
{
|
|
exportBackground,
|
|
exportPadding = 10,
|
|
viewBackgroundColor,
|
|
scale = 1,
|
|
}: {
|
|
exportBackground: boolean;
|
|
exportPadding?: number;
|
|
scale?: number;
|
|
viewBackgroundColor: string;
|
|
},
|
|
createCanvas: (width: number, height: number) => any = function(
|
|
width,
|
|
height,
|
|
) {
|
|
const tempCanvas = document.createElement("canvas");
|
|
tempCanvas.width = width * scale;
|
|
tempCanvas.height = height * scale;
|
|
return tempCanvas;
|
|
},
|
|
) {
|
|
// calculate smallest area to fit the contents in
|
|
const [minX, minY, maxX, maxY] = getCommonBounds(elements);
|
|
const width = distance(minX, maxX) + exportPadding * 2;
|
|
const height = distance(minY, maxY) + exportPadding * 2;
|
|
|
|
const tempCanvas: any = createCanvas(width, height);
|
|
|
|
renderScene(
|
|
elements,
|
|
appState,
|
|
null,
|
|
scale,
|
|
rough.canvas(tempCanvas),
|
|
tempCanvas,
|
|
{
|
|
viewBackgroundColor: exportBackground ? viewBackgroundColor : null,
|
|
scrollX: normalizeScroll(-minX + exportPadding),
|
|
scrollY: normalizeScroll(-minY + exportPadding),
|
|
zoom: 1,
|
|
remotePointerViewportCoords: {},
|
|
remotePointerUsernames: {},
|
|
},
|
|
{
|
|
renderScrollbars: false,
|
|
renderSelection: false,
|
|
renderOptimizations: false,
|
|
},
|
|
);
|
|
return tempCanvas;
|
|
}
|
|
|
|
export function exportToSvg(
|
|
elements: readonly ExcalidrawElement[],
|
|
{
|
|
exportBackground,
|
|
exportPadding = 10,
|
|
viewBackgroundColor,
|
|
}: {
|
|
exportBackground: boolean;
|
|
exportPadding?: number;
|
|
viewBackgroundColor: string;
|
|
},
|
|
): SVGSVGElement {
|
|
// calculate canvas dimensions
|
|
const [minX, minY, maxX, maxY] = getCommonBounds(elements);
|
|
const width = distance(minX, maxX) + exportPadding * 2;
|
|
const height = distance(minY, maxY) + exportPadding * 2;
|
|
|
|
// initialze SVG root
|
|
const svgRoot = document.createElementNS(SVG_NS, "svg");
|
|
svgRoot.setAttribute("version", "1.1");
|
|
svgRoot.setAttribute("xmlns", SVG_NS);
|
|
svgRoot.setAttribute("viewBox", `0 0 ${width} ${height}`);
|
|
|
|
svgRoot.innerHTML = `
|
|
<defs>
|
|
<style>
|
|
@font-face {
|
|
font-family: "Virgil";
|
|
src: url("https://excalidraw.com/FG_Virgil.ttf");
|
|
}
|
|
@font-face {
|
|
font-family: "Cascadia";
|
|
src: url("https://excalidraw.com/Cascadia.ttf");
|
|
}
|
|
</style>
|
|
</defs>
|
|
`;
|
|
|
|
// render backgroiund rect
|
|
if (exportBackground && viewBackgroundColor) {
|
|
const rect = svgRoot.ownerDocument!.createElementNS(SVG_NS, "rect");
|
|
rect.setAttribute("x", "0");
|
|
rect.setAttribute("y", "0");
|
|
rect.setAttribute("width", `${width}`);
|
|
rect.setAttribute("height", `${height}`);
|
|
rect.setAttribute("fill", viewBackgroundColor);
|
|
svgRoot.appendChild(rect);
|
|
}
|
|
|
|
const rsvg = rough.svg(svgRoot);
|
|
renderSceneToSvg(elements, rsvg, svgRoot, {
|
|
offsetX: -minX + exportPadding,
|
|
offsetY: -minY + exportPadding,
|
|
});
|
|
return svgRoot;
|
|
}
|