Browse Source

feat: add triangle arrowhead (#4024)

Co-authored-by: ad1992 <aakansha1216@gmail.com>
Co-authored-by: dwelle <luzar.david@gmail.com>
Jonas Bleyl 3 năm trước cách đây
mục cha
commit
8d8769ba4e

+ 17 - 0
src/actions/actionProperties.tsx

@@ -6,6 +6,7 @@ import {
   ArrowheadArrowIcon,
   ArrowheadBarIcon,
   ArrowheadDotIcon,
+  ArrowheadTriangleIcon,
   ArrowheadNoneIcon,
   EdgeRoundIcon,
   EdgeSharpIcon,
@@ -738,6 +739,14 @@ export const actionChangeArrowhead = register({
                 icon: <ArrowheadDotIcon theme={appState.theme} flip={!isRTL} />,
                 keyBinding: "r",
               },
+              {
+                value: "triangle",
+                text: t("labels.arrowhead_triangle"),
+                icon: (
+                  <ArrowheadTriangleIcon theme={appState.theme} flip={!isRTL} />
+                ),
+                keyBinding: "t",
+              },
             ]}
             value={getFormValue<Arrowhead | null>(
               elements,
@@ -780,6 +789,14 @@ export const actionChangeArrowhead = register({
                 keyBinding: "r",
                 icon: <ArrowheadDotIcon theme={appState.theme} flip={isRTL} />,
               },
+              {
+                value: "triangle",
+                text: t("labels.arrowhead_triangle"),
+                icon: (
+                  <ArrowheadTriangleIcon theme={appState.theme} flip={isRTL} />
+                ),
+                keyBinding: "t",
+              },
             ]}
             value={getFormValue<Arrowhead | null>(
               elements,

+ 1 - 1
src/components/IconPicker.scss

@@ -90,7 +90,7 @@
   .picker-content {
     padding: 0.5rem;
     display: grid;
-    grid-auto-flow: column;
+    grid-template-columns: repeat(3, auto);
     grid-gap: 0.5rem;
     border-radius: 4px;
     :root[dir="rtl"] & {

+ 15 - 0
src/components/icons.tsx

@@ -752,6 +752,21 @@ export const ArrowheadBarIcon = React.memo(
     ),
 );
 
+export const ArrowheadTriangleIcon = React.memo(
+  ({ theme, flip = false }: { theme: Theme; flip?: boolean }) =>
+    createIcon(
+      <g
+        stroke={iconFillColor(theme)}
+        fill={iconFillColor(theme)}
+        transform={flip ? "translate(40, 0) scale(-1, 1)" : ""}
+      >
+        <path d="M32 10L6 10" strokeWidth={2} />
+        <path d="M27.5 5.5L34.5 10L27.5 14.5L27.5 5.5" />
+      </g>,
+      { width: 40, height: 20 },
+    ),
+);
+
 export const FontSizeSmallIcon = React.memo(({ theme }: { theme: Theme }) =>
   createIcon(
     <path

+ 2 - 0
src/element/bounds.ts

@@ -258,6 +258,7 @@ export const getArrowheadPoints = (
     arrow: 30,
     bar: 15,
     dot: 15,
+    triangle: 15,
   }[arrowhead]; // pixels (will differ for each arrowhead)
 
   let length = 0;
@@ -294,6 +295,7 @@ export const getArrowheadPoints = (
   const angle = {
     arrow: 20,
     bar: 90,
+    triangle: 25,
   }[arrowhead]; // degrees
 
   // Return points

+ 1 - 1
src/element/types.ts

@@ -129,7 +129,7 @@ export type PointBinding = {
   gap: number;
 };
 
-export type Arrowhead = "arrow" | "bar" | "dot";
+export type Arrowhead = "arrow" | "bar" | "dot" | "triangle";
 
 export type ExcalidrawLinearElement = _ExcalidrawElementBase &
   Readonly<{

+ 1 - 0
src/locales/en.json

@@ -39,6 +39,7 @@
     "arrowhead_arrow": "Arrow",
     "arrowhead_bar": "Bar",
     "arrowhead_dot": "Dot",
+    "arrowhead_triangle": "Triangle",
     "fontSize": "Font size",
     "fontFamily": "Font family",
     "onlySelected": "Only selected",

+ 23 - 0
src/renderer/renderElement.ts

@@ -485,6 +485,29 @@ const generateElementShape = (
               ];
             }
 
+            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;