2020-01-07 19:04:52 +04:00
|
|
|
import { ExcalidrawElement } from "../element/types";
|
|
|
|
import { isTextElement } from "../element/typeChecks";
|
|
|
|
import { getDiamondPoints, getArrowPoints } from "../element/bounds";
|
|
|
|
import { RoughCanvas } from "roughjs/bin/canvas";
|
2020-01-12 04:00:00 +04:00
|
|
|
import { Drawable } from "roughjs/bin/core";
|
2020-01-06 19:34:22 +04:00
|
|
|
|
2020-01-07 19:04:52 +04:00
|
|
|
export function renderElement(
|
|
|
|
element: ExcalidrawElement,
|
|
|
|
rc: RoughCanvas,
|
2020-01-12 03:38:41 +05:00
|
|
|
context: CanvasRenderingContext2D
|
2020-01-07 19:04:52 +04:00
|
|
|
) {
|
2020-01-12 03:38:41 +05:00
|
|
|
const generator = rc.generator;
|
2020-01-06 19:34:22 +04:00
|
|
|
if (element.type === "selection") {
|
2020-01-07 19:04:52 +04:00
|
|
|
const fillStyle = context.fillStyle;
|
|
|
|
context.fillStyle = "rgba(0, 0, 255, 0.10)";
|
2020-01-12 03:38:41 +05:00
|
|
|
context.fillRect(0, 0, element.width, element.height);
|
2020-01-07 19:04:52 +04:00
|
|
|
context.fillStyle = fillStyle;
|
2020-01-06 19:34:22 +04:00
|
|
|
} else if (element.type === "rectangle") {
|
2020-01-12 04:00:00 +04:00
|
|
|
if (!element.shape) {
|
2020-01-13 11:04:28 -08:00
|
|
|
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,
|
|
|
|
seed: element.seed
|
2020-01-12 04:00:00 +04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
context.globalAlpha = element.opacity / 100;
|
|
|
|
rc.draw(element.shape as Drawable);
|
|
|
|
context.globalAlpha = 1;
|
|
|
|
} else if (element.type === "diamond") {
|
|
|
|
if (!element.shape) {
|
2020-01-13 11:04:28 -08:00
|
|
|
const [
|
|
|
|
topX,
|
|
|
|
topY,
|
|
|
|
rightX,
|
|
|
|
rightY,
|
|
|
|
bottomX,
|
|
|
|
bottomY,
|
|
|
|
leftX,
|
|
|
|
leftY
|
|
|
|
] = getDiamondPoints(element);
|
|
|
|
element.shape = generator.polygon(
|
|
|
|
[
|
|
|
|
[topX, topY],
|
|
|
|
[rightX, rightY],
|
|
|
|
[bottomX, bottomY],
|
|
|
|
[leftX, leftY]
|
|
|
|
],
|
|
|
|
{
|
|
|
|
stroke: element.strokeColor,
|
|
|
|
fill:
|
|
|
|
element.backgroundColor === "transparent"
|
|
|
|
? undefined
|
|
|
|
: element.backgroundColor,
|
|
|
|
fillStyle: element.fillStyle,
|
|
|
|
strokeWidth: element.strokeWidth,
|
|
|
|
roughness: element.roughness,
|
|
|
|
seed: element.seed
|
|
|
|
}
|
|
|
|
);
|
2020-01-12 04:00:00 +04:00
|
|
|
}
|
|
|
|
|
2020-01-07 19:04:52 +04:00
|
|
|
context.globalAlpha = element.opacity / 100;
|
2020-01-12 04:00:00 +04:00
|
|
|
rc.draw(element.shape as Drawable);
|
2020-01-07 19:04:52 +04:00
|
|
|
context.globalAlpha = 1;
|
2020-01-06 19:34:22 +04:00
|
|
|
} else if (element.type === "ellipse") {
|
2020-01-12 04:00:00 +04:00
|
|
|
if (!element.shape) {
|
2020-01-13 11:04:28 -08:00
|
|
|
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,
|
2020-01-15 20:01:50 +01:00
|
|
|
seed: element.seed,
|
|
|
|
curveFitting: 1
|
2020-01-13 11:04:28 -08:00
|
|
|
}
|
2020-01-12 04:00:00 +04:00
|
|
|
);
|
|
|
|
}
|
2020-01-07 19:04:52 +04:00
|
|
|
|
|
|
|
context.globalAlpha = element.opacity / 100;
|
2020-01-12 04:00:00 +04:00
|
|
|
rc.draw(element.shape as Drawable);
|
2020-01-07 19:04:52 +04:00
|
|
|
context.globalAlpha = 1;
|
2020-01-06 19:34:22 +04:00
|
|
|
} else if (element.type === "arrow") {
|
|
|
|
const [x1, y1, x2, y2, x3, y3, x4, y4] = getArrowPoints(element);
|
|
|
|
const options = {
|
|
|
|
stroke: element.strokeColor,
|
|
|
|
strokeWidth: element.strokeWidth,
|
2020-01-13 11:04:28 -08:00
|
|
|
roughness: element.roughness,
|
|
|
|
seed: element.seed
|
2020-01-06 19:34:22 +04:00
|
|
|
};
|
|
|
|
|
2020-01-12 04:00:00 +04:00
|
|
|
if (!element.shape) {
|
2020-01-13 11:04:28 -08:00
|
|
|
element.shape = [
|
2020-01-12 04:00:00 +04:00
|
|
|
// \
|
|
|
|
generator.line(x3, y3, x2, y2, options),
|
|
|
|
// -----
|
|
|
|
generator.line(x1, y1, x2, y2, options),
|
|
|
|
// /
|
|
|
|
generator.line(x4, y4, x2, y2, options)
|
2020-01-13 11:04:28 -08:00
|
|
|
];
|
2020-01-12 04:00:00 +04:00
|
|
|
}
|
2020-01-06 19:34:22 +04:00
|
|
|
|
2020-01-07 19:04:52 +04:00
|
|
|
context.globalAlpha = element.opacity / 100;
|
2020-01-12 04:00:00 +04:00
|
|
|
(element.shape as Drawable[]).forEach(shape => rc.draw(shape));
|
2020-01-07 19:04:52 +04:00
|
|
|
context.globalAlpha = 1;
|
2020-01-06 19:34:22 +04:00
|
|
|
return;
|
|
|
|
} else if (isTextElement(element)) {
|
2020-01-07 19:04:52 +04:00
|
|
|
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,
|
2020-01-12 03:38:41 +05:00
|
|
|
0,
|
|
|
|
element.baseline || element.actualBoundingBoxAscent || 0
|
2020-01-07 19:04:52 +04:00
|
|
|
);
|
|
|
|
context.fillStyle = fillStyle;
|
|
|
|
context.font = font;
|
|
|
|
context.globalAlpha = 1;
|
2020-01-06 19:34:22 +04:00
|
|
|
} else {
|
|
|
|
throw new Error("Unimplemented type " + element.type);
|
|
|
|
}
|
|
|
|
}
|