mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
Add Arrowheads to Arrows (#2452)
Co-authored-by: dwelle <luzar.david@gmail.com> Co-authored-by: Lipis <lipiridis@gmail.com>
This commit is contained in:
parent
bd8e860d7f
commit
c291edfc44
25 changed files with 711 additions and 101 deletions
|
@ -4,15 +4,19 @@ import {
|
|||
ExcalidrawTextElement,
|
||||
TextAlign,
|
||||
FontFamily,
|
||||
ExcalidrawLinearElement,
|
||||
Arrowhead,
|
||||
} from "../element/types";
|
||||
import {
|
||||
getCommonAttributeOfSelectedElements,
|
||||
isSomeElementSelected,
|
||||
getTargetElements,
|
||||
canChangeSharpness,
|
||||
canHaveArrowheads,
|
||||
} from "../scene";
|
||||
import { ButtonSelect } from "../components/ButtonSelect";
|
||||
import { ButtonIconSelect } from "../components/ButtonIconSelect";
|
||||
import { ButtonIconCycle } from "../components/ButtonIconCycle";
|
||||
import {
|
||||
isTextElement,
|
||||
redrawTextBoundingBox,
|
||||
|
@ -39,6 +43,7 @@ import {
|
|||
SloppinessArchitectIcon,
|
||||
SloppinessArtistIcon,
|
||||
SloppinessCartoonistIcon,
|
||||
ArrowArrowheadIcon,
|
||||
} from "../components/icons";
|
||||
import { EVENT_CHANGE, trackEvent } from "../analytics";
|
||||
import colors from "../colors";
|
||||
|
@ -622,3 +627,110 @@ export const actionChangeSharpness = register({
|
|||
</fieldset>
|
||||
),
|
||||
});
|
||||
|
||||
export const actionChangeArrowhead = register({
|
||||
name: "changeArrowhead",
|
||||
perform: (
|
||||
elements,
|
||||
appState,
|
||||
value: { position: "start" | "end"; type: Arrowhead },
|
||||
) => {
|
||||
return {
|
||||
elements: changeProperty(elements, appState, (el) => {
|
||||
if (isLinearElement(el)) {
|
||||
trackEvent(
|
||||
EVENT_CHANGE,
|
||||
`arrowhead ${value.position}`,
|
||||
value.type || "none",
|
||||
);
|
||||
|
||||
const { position, type } = value;
|
||||
|
||||
if (position === "start") {
|
||||
const element: ExcalidrawLinearElement = newElementWith(el, {
|
||||
startArrowhead: type,
|
||||
});
|
||||
return element;
|
||||
} else if (position === "end") {
|
||||
const element: ExcalidrawLinearElement = newElementWith(el, {
|
||||
endArrowhead: type,
|
||||
});
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
return el;
|
||||
}),
|
||||
appState: {
|
||||
...appState,
|
||||
currentItemArrowheads: {
|
||||
...appState.currentItemArrowheads,
|
||||
[value.position]: value.type,
|
||||
},
|
||||
},
|
||||
commitToHistory: true,
|
||||
};
|
||||
},
|
||||
PanelComponent: ({ elements, appState, updateData }) => (
|
||||
<fieldset>
|
||||
<legend>{t("labels.arrowheads")}</legend>
|
||||
<div className="buttonList buttonListIcon">
|
||||
<ButtonIconCycle
|
||||
group="arrowhead_start"
|
||||
options={[
|
||||
{
|
||||
value: null,
|
||||
text: t("labels.arrowhead_none"),
|
||||
icon: <StrokeStyleSolidIcon appearance={appState.appearance} />,
|
||||
},
|
||||
{
|
||||
value: "arrow",
|
||||
text: t("labels.arrowhead_arrow"),
|
||||
icon: (
|
||||
<ArrowArrowheadIcon
|
||||
appearance={appState.appearance}
|
||||
flip={true}
|
||||
/>
|
||||
),
|
||||
},
|
||||
]}
|
||||
value={getFormValue<Arrowhead | null>(
|
||||
elements,
|
||||
appState,
|
||||
(element) =>
|
||||
isLinearElement(element) && canHaveArrowheads(element.type)
|
||||
? element.startArrowhead
|
||||
: appState.currentItemArrowheads.start,
|
||||
appState.currentItemArrowheads.start,
|
||||
)}
|
||||
onChange={(value) => updateData({ position: "start", type: value })}
|
||||
/>
|
||||
<ButtonIconCycle
|
||||
group="arrowhead_end"
|
||||
options={[
|
||||
{
|
||||
value: null,
|
||||
text: t("labels.arrowhead_none"),
|
||||
icon: <StrokeStyleSolidIcon appearance={appState.appearance} />,
|
||||
},
|
||||
{
|
||||
value: "arrow",
|
||||
text: t("labels.arrowhead_arrow"),
|
||||
icon: <ArrowArrowheadIcon appearance={appState.appearance} />,
|
||||
},
|
||||
]}
|
||||
value={getFormValue<Arrowhead | null>(
|
||||
elements,
|
||||
appState,
|
||||
(element) =>
|
||||
isLinearElement(element) && canHaveArrowheads(element.type)
|
||||
? element.endArrowhead
|
||||
: appState.currentItemArrowheads.end,
|
||||
appState.currentItemArrowheads.end,
|
||||
)}
|
||||
onChange={(value) => updateData({ position: "end", type: value })}
|
||||
/>
|
||||
</div>
|
||||
</fieldset>
|
||||
),
|
||||
});
|
||||
|
|
|
@ -35,6 +35,7 @@ export type ActionName =
|
|||
| "changeStrokeWidth"
|
||||
| "changeSloppiness"
|
||||
| "changeStrokeStyle"
|
||||
| "changeArrowhead"
|
||||
| "changeOpacity"
|
||||
| "changeFontSize"
|
||||
| "toggleCanvasMenu"
|
||||
|
@ -99,9 +100,7 @@ export interface Action {
|
|||
}
|
||||
|
||||
export interface ActionsManagerInterface {
|
||||
actions: {
|
||||
[actionName in ActionName]: Action;
|
||||
};
|
||||
actions: Record<ActionName, Action>;
|
||||
registerAction: (action: Action) => void;
|
||||
handleKeyDown: (event: KeyboardEvent) => boolean;
|
||||
getContextMenuItems: (
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue