excalidraw/src/renderer/renderElement.ts

159 lines
4.5 KiB
TypeScript
Raw Normal View History

import { ExcalidrawElement } from "../element/types";
import { isTextElement } from "../element/typeChecks";
import {
getDiamondPoints,
getArrowPoints,
2020-01-24 12:04:54 +02:00
getLinePoints,
} from "../element/bounds";
import { RoughCanvas } from "roughjs/bin/canvas";
import { Drawable } from "roughjs/bin/core";
export function renderElement(
element: ExcalidrawElement,
rc: RoughCanvas,
2020-01-24 12:04:54 +02:00
context: CanvasRenderingContext2D,
) {
const generator = rc.generator;
if (element.type === "selection") {
const fillStyle = context.fillStyle;
context.fillStyle = "rgba(0, 0, 255, 0.10)";
context.fillRect(0, 0, element.width, element.height);
context.fillStyle = fillStyle;
} else if (element.type === "rectangle") {
if (!element.shape) {
element.shape = generator.rectangle(0, 0, element.width, element.height, {
stroke: element.strokeColor,
fill:
element.backgroundColor === "transparent"
? undefined
: element.backgroundColor,
fillStyle: element.fillStyle,
strokeWidth: element.strokeWidth,
roughness: element.roughness,
2020-01-24 12:04:54 +02:00
seed: element.seed,
});
}
context.globalAlpha = element.opacity / 100;
rc.draw(element.shape as Drawable);
context.globalAlpha = 1;
} else if (element.type === "diamond") {
if (!element.shape) {
const [
topX,
topY,
rightX,
rightY,
bottomX,
bottomY,
leftX,
2020-01-24 12:04:54 +02:00
leftY,
] = getDiamondPoints(element);
element.shape = generator.polygon(
[
[topX, topY],
[rightX, rightY],
[bottomX, bottomY],
2020-01-24 12:04:54 +02:00
[leftX, leftY],
],
{
stroke: element.strokeColor,
fill:
element.backgroundColor === "transparent"
? undefined
: element.backgroundColor,
fillStyle: element.fillStyle,
strokeWidth: element.strokeWidth,
roughness: element.roughness,
2020-01-24 12:04:54 +02:00
seed: element.seed,
},
);
}
context.globalAlpha = element.opacity / 100;
rc.draw(element.shape as Drawable);
context.globalAlpha = 1;
} else if (element.type === "ellipse") {
if (!element.shape) {
element.shape = generator.ellipse(
element.width / 2,
element.height / 2,
element.width,
element.height,
{
stroke: element.strokeColor,
fill:
element.backgroundColor === "transparent"
? undefined
: element.backgroundColor,
fillStyle: element.fillStyle,
strokeWidth: element.strokeWidth,
roughness: element.roughness,
seed: element.seed,
2020-01-24 12:04:54 +02:00
curveFitting: 1,
},
);
}
context.globalAlpha = element.opacity / 100;
rc.draw(element.shape as Drawable);
context.globalAlpha = 1;
} else if (element.type === "arrow") {
const [x1, y1, x2, y2, x3, y3, x4, y4] = getArrowPoints(element);
const options = {
stroke: element.strokeColor,
strokeWidth: element.strokeWidth,
roughness: element.roughness,
2020-01-24 12:04:54 +02:00
seed: element.seed,
};
if (!element.shape) {
element.shape = [
// \
generator.line(x3, y3, x2, y2, options),
// -----
generator.line(x1, y1, x2, y2, options),
// /
2020-01-24 12:04:54 +02:00
generator.line(x4, y4, x2, y2, options),
];
}
context.globalAlpha = element.opacity / 100;
(element.shape as Drawable[]).forEach(shape => rc.draw(shape));
context.globalAlpha = 1;
return;
} else if (element.type === "line") {
const [x1, y1, x2, y2] = getLinePoints(element);
const options = {
stroke: element.strokeColor,
strokeWidth: element.strokeWidth,
roughness: element.roughness,
2020-01-24 12:04:54 +02:00
seed: element.seed,
};
if (!element.shape) {
element.shape = generator.line(x1, y1, x2, y2, options);
}
context.globalAlpha = element.opacity / 100;
rc.draw(element.shape as Drawable);
context.globalAlpha = 1;
} else if (isTextElement(element)) {
context.globalAlpha = element.opacity / 100;
const font = context.font;
context.font = element.font;
const fillStyle = context.fillStyle;
context.fillStyle = element.strokeColor;
context.fillText(
element.text,
0,
2020-01-24 12:04:54 +02:00
element.baseline || element.actualBoundingBoxAscent || 0,
);
context.fillStyle = fillStyle;
context.font = font;
context.globalAlpha = 1;
} else {
throw new Error("Unimplemented type " + element.type);
}
}