mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
feat: add support for more UML arrowheads (#7391)
This commit is contained in:
parent
a04cc707c3
commit
b9cfbc2077
15 changed files with 449 additions and 216 deletions
|
@ -145,6 +145,126 @@ const modifyIframeLikeForRoughOptions = (
|
|||
return element;
|
||||
};
|
||||
|
||||
const getArrowheadShapes = (
|
||||
element: ExcalidrawLinearElement,
|
||||
shape: Drawable[],
|
||||
position: "start" | "end",
|
||||
arrowhead: Arrowhead,
|
||||
generator: RoughGenerator,
|
||||
options: Options,
|
||||
canvasBackgroundColor: string,
|
||||
) => {
|
||||
const arrowheadPoints = getArrowheadPoints(
|
||||
element,
|
||||
shape,
|
||||
position,
|
||||
arrowhead,
|
||||
);
|
||||
|
||||
if (arrowheadPoints === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
switch (arrowhead) {
|
||||
case "dot":
|
||||
case "circle":
|
||||
case "circle_outline": {
|
||||
const [x, y, diameter] = arrowheadPoints;
|
||||
|
||||
// always use solid stroke for arrowhead
|
||||
delete options.strokeLineDash;
|
||||
|
||||
return [
|
||||
generator.circle(x, y, diameter, {
|
||||
...options,
|
||||
fill:
|
||||
arrowhead === "circle_outline"
|
||||
? canvasBackgroundColor
|
||||
: element.strokeColor,
|
||||
|
||||
fillStyle: "solid",
|
||||
stroke: element.strokeColor,
|
||||
roughness: Math.min(0.5, options.roughness || 0),
|
||||
}),
|
||||
];
|
||||
}
|
||||
case "triangle":
|
||||
case "triangle_outline": {
|
||||
const [x, y, x2, y2, x3, y3] = arrowheadPoints;
|
||||
|
||||
// always use solid stroke for arrowhead
|
||||
delete options.strokeLineDash;
|
||||
|
||||
return [
|
||||
generator.polygon(
|
||||
[
|
||||
[x, y],
|
||||
[x2, y2],
|
||||
[x3, y3],
|
||||
[x, y],
|
||||
],
|
||||
{
|
||||
...options,
|
||||
fill:
|
||||
arrowhead === "triangle_outline"
|
||||
? canvasBackgroundColor
|
||||
: element.strokeColor,
|
||||
fillStyle: "solid",
|
||||
roughness: Math.min(1, options.roughness || 0),
|
||||
},
|
||||
),
|
||||
];
|
||||
}
|
||||
case "diamond":
|
||||
case "diamond_outline": {
|
||||
const [x, y, x2, y2, x3, y3, x4, y4] = arrowheadPoints;
|
||||
|
||||
// always use solid stroke for arrowhead
|
||||
delete options.strokeLineDash;
|
||||
|
||||
return [
|
||||
generator.polygon(
|
||||
[
|
||||
[x, y],
|
||||
[x2, y2],
|
||||
[x3, y3],
|
||||
[x4, y4],
|
||||
[x, y],
|
||||
],
|
||||
{
|
||||
...options,
|
||||
fill:
|
||||
arrowhead === "diamond_outline"
|
||||
? canvasBackgroundColor
|
||||
: element.strokeColor,
|
||||
fillStyle: "solid",
|
||||
roughness: Math.min(1, options.roughness || 0),
|
||||
},
|
||||
),
|
||||
];
|
||||
}
|
||||
case "bar":
|
||||
case "arrow":
|
||||
default: {
|
||||
const [x2, y2, x3, y3, x4, y4] = arrowheadPoints;
|
||||
|
||||
if (element.strokeStyle === "dotted") {
|
||||
// for dotted arrows caps, reduce gap to make it more legible
|
||||
const dash = getDashArrayDotted(element.strokeWidth - 1);
|
||||
options.strokeLineDash = [dash[0], dash[1] - 1];
|
||||
} else {
|
||||
// for solid/dashed, keep solid arrow cap
|
||||
delete options.strokeLineDash;
|
||||
}
|
||||
options.roughness = Math.min(1, options.roughness || 0);
|
||||
return [
|
||||
generator.line(x3, y3, x2, y2, options),
|
||||
generator.line(x4, y4, x2, y2, options),
|
||||
];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates the roughjs shape for given element.
|
||||
*
|
||||
|
@ -155,7 +275,10 @@ const modifyIframeLikeForRoughOptions = (
|
|||
export const _generateElementShape = (
|
||||
element: Exclude<NonDeletedExcalidrawElement, ExcalidrawSelectionElement>,
|
||||
generator: RoughGenerator,
|
||||
isExporting: boolean = false,
|
||||
{
|
||||
isExporting,
|
||||
canvasBackgroundColor,
|
||||
}: { isExporting: boolean; canvasBackgroundColor: string },
|
||||
): Drawable | Drawable[] | null => {
|
||||
switch (element.type) {
|
||||
case "rectangle":
|
||||
|
@ -276,83 +399,15 @@ export const _generateElementShape = (
|
|||
if (element.type === "arrow") {
|
||||
const { startArrowhead = null, endArrowhead = "arrow" } = element;
|
||||
|
||||
const getArrowheadShapes = (
|
||||
element: ExcalidrawLinearElement,
|
||||
shape: Drawable[],
|
||||
position: "start" | "end",
|
||||
arrowhead: Arrowhead,
|
||||
) => {
|
||||
const arrowheadPoints = getArrowheadPoints(
|
||||
element,
|
||||
shape,
|
||||
position,
|
||||
arrowhead,
|
||||
);
|
||||
|
||||
if (arrowheadPoints === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Other arrowheads here...
|
||||
if (arrowhead === "dot") {
|
||||
const [x, y, r] = arrowheadPoints;
|
||||
|
||||
return [
|
||||
generator.circle(x, y, r, {
|
||||
...options,
|
||||
fill: element.strokeColor,
|
||||
fillStyle: "solid",
|
||||
stroke: "none",
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
if (arrowhead === "triangle") {
|
||||
const [x, y, x2, y2, x3, y3] = arrowheadPoints;
|
||||
|
||||
// always use solid stroke for triangle arrowhead
|
||||
delete options.strokeLineDash;
|
||||
|
||||
return [
|
||||
generator.polygon(
|
||||
[
|
||||
[x, y],
|
||||
[x2, y2],
|
||||
[x3, y3],
|
||||
[x, y],
|
||||
],
|
||||
{
|
||||
...options,
|
||||
fill: element.strokeColor,
|
||||
fillStyle: "solid",
|
||||
},
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
// Arrow arrowheads
|
||||
const [x2, y2, x3, y3, x4, y4] = arrowheadPoints;
|
||||
|
||||
if (element.strokeStyle === "dotted") {
|
||||
// for dotted arrows caps, reduce gap to make it more legible
|
||||
const dash = getDashArrayDotted(element.strokeWidth - 1);
|
||||
options.strokeLineDash = [dash[0], dash[1] - 1];
|
||||
} else {
|
||||
// for solid/dashed, keep solid arrow cap
|
||||
delete options.strokeLineDash;
|
||||
}
|
||||
return [
|
||||
generator.line(x3, y3, x2, y2, options),
|
||||
generator.line(x4, y4, x2, y2, options),
|
||||
];
|
||||
};
|
||||
|
||||
if (startArrowhead !== null) {
|
||||
const shapes = getArrowheadShapes(
|
||||
element,
|
||||
shape,
|
||||
"start",
|
||||
startArrowhead,
|
||||
generator,
|
||||
options,
|
||||
canvasBackgroundColor,
|
||||
);
|
||||
shape.push(...shapes);
|
||||
}
|
||||
|
@ -367,6 +422,9 @@ export const _generateElementShape = (
|
|||
shape,
|
||||
"end",
|
||||
endArrowhead,
|
||||
generator,
|
||||
options,
|
||||
canvasBackgroundColor,
|
||||
);
|
||||
shape.push(...shapes);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue