瀏覽代碼

adjust crop handles

Ryan Di 10 月之前
父節點
當前提交
a02c4cb140
共有 1 個文件被更改,包括 98 次插入87 次删除
  1. 98 87
      packages/excalidraw/renderer/interactiveScene.ts

+ 98 - 87
packages/excalidraw/renderer/interactiveScene.ts

@@ -305,38 +305,42 @@ const renderBindingHighlightForSuggestedPointBinding = (
   });
 };
 
+type ElementSelectionBorder = {
+  angle: number;
+  x1: number;
+  y1: number;
+  x2: number;
+  y2: number;
+  selectionColors: string[];
+  dashed?: boolean;
+  cx: number;
+  cy: number;
+  activeEmbeddable: boolean;
+  padding?: number;
+};
+
 const renderSelectionBorder = (
   context: CanvasRenderingContext2D,
   appState: InteractiveCanvasAppState,
-  elementProperties: {
-    angle: number;
-    elementX1: number;
-    elementY1: number;
-    elementX2: number;
-    elementY2: number;
-    selectionColors: string[];
-    dashed?: boolean;
-    cx: number;
-    cy: number;
-    activeEmbeddable: boolean;
-  },
+  elementProperties: ElementSelectionBorder,
 ) => {
   const {
     angle,
-    elementX1,
-    elementY1,
-    elementX2,
-    elementY2,
+    x1,
+    y1,
+    x2,
+    y2,
     selectionColors,
     cx,
     cy,
     dashed,
     activeEmbeddable,
   } = elementProperties;
-  const elementWidth = elementX2 - elementX1;
-  const elementHeight = elementY2 - elementY1;
+  const elementWidth = x2 - x1;
+  const elementHeight = y2 - y1;
 
-  const padding = DEFAULT_TRANSFORM_HANDLE_SPACING * 2;
+  const padding =
+    elementProperties.padding ?? DEFAULT_TRANSFORM_HANDLE_SPACING * 2;
 
   const linePadding = padding / appState.zoom.value;
   const lineWidth = 8 / appState.zoom.value;
@@ -358,8 +362,8 @@ const renderSelectionBorder = (
     context.lineDashOffset = (lineWidth + spaceWidth) * index;
     strokeRectWithRotation(
       context,
-      elementX1 - linePadding,
-      elementY1 - linePadding,
+      x1 - linePadding,
+      y1 - linePadding,
       elementWidth + linePadding * 2,
       elementHeight + linePadding * 2,
       cx,
@@ -431,18 +435,17 @@ const renderElementsBoxHighlight = (
   );
 
   const getSelectionFromElements = (elements: ExcalidrawElement[]) => {
-    const [elementX1, elementY1, elementX2, elementY2] =
-      getCommonBounds(elements);
+    const [x1, y1, x2, y2] = getCommonBounds(elements);
     return {
       angle: 0,
-      elementX1,
-      elementX2,
-      elementY1,
-      elementY2,
+      x1,
+      x2,
+      y1,
+      y2,
       selectionColors: ["rgb(0,118,255)"],
       dashed: false,
-      cx: elementX1 + (elementX2 - elementX1) / 2,
-      cy: elementY1 + (elementY2 - elementY1) / 2,
+      cx: x1 + (x2 - x1) / 2,
+      cy: y1 + (y2 - y1) / 2,
       activeEmbeddable: false,
     };
   };
@@ -599,24 +602,33 @@ const renderCropHandles = (
   croppingElement: ExcalidrawImageElement,
   elementsMap: ElementsMap,
 ): void => {
-  const lineWidth = 3 / appState.zoom.value;
-  const length = 15 / appState.zoom.value;
-
   const [x1, y1, , , cx, cy] = getElementAbsoluteCoords(
     croppingElement,
     elementsMap,
   );
-  const halfWidth =
-    cx - x1 + (DEFAULT_TRANSFORM_HANDLE_SPACING * 2) / appState.zoom.value;
-  const halfHeight =
-    cy - y1 + (DEFAULT_TRANSFORM_HANDLE_SPACING * 2) / appState.zoom.value;
+
+  const LINE_WIDTH = 3;
+  const LINE_LENGTH = 20;
+
+  const ZOOMED_LINE_WIDTH = LINE_WIDTH / appState.zoom.value;
+  const ZOOMED_HALF_LINE_WIDTH = ZOOMED_LINE_WIDTH / 2;
+
+  const HALF_WIDTH = cx - x1 + ZOOMED_LINE_WIDTH;
+  const HALF_HEIGHT = cy - y1 + ZOOMED_LINE_WIDTH;
+
+  const HORIZONTAL_LINE_LENGTH = Math.min(
+    LINE_LENGTH / appState.zoom.value,
+    HALF_WIDTH,
+  );
+  const VERTICAL_LINE_LENGTH = Math.min(
+    LINE_LENGTH / appState.zoom.value,
+    HALF_HEIGHT,
+  );
 
   context.save();
   context.fillStyle = renderConfig.selectionColor;
   context.strokeStyle = renderConfig.selectionColor;
-  context.lineWidth = lineWidth;
-
-  const halfLineWidth = lineWidth / 2;
+  context.lineWidth = ZOOMED_LINE_WIDTH;
 
   const handles: Array<
     [
@@ -629,34 +641,40 @@ const renderCropHandles = (
   > = [
     [
       // x, y
-      [-halfWidth, -halfHeight],
-      // first start and t0
-      [0, halfLineWidth],
-      [length, halfLineWidth],
-      // second  start and to
-      [halfLineWidth, 0],
-      [halfLineWidth, length - halfLineWidth],
+      [-HALF_WIDTH, -HALF_HEIGHT],
+      // horizontal line: first start and to
+      [0, ZOOMED_HALF_LINE_WIDTH],
+      [HORIZONTAL_LINE_LENGTH, ZOOMED_HALF_LINE_WIDTH],
+      // vertical line: second  start and to
+      [ZOOMED_HALF_LINE_WIDTH, 0],
+      [ZOOMED_HALF_LINE_WIDTH, VERTICAL_LINE_LENGTH],
     ],
     [
-      [halfWidth - halfLineWidth, -halfHeight + halfLineWidth],
-      [halfLineWidth, 0],
-      [-length + halfLineWidth, 0],
-      [0, -halfLineWidth],
-      [0, length - lineWidth],
+      [HALF_WIDTH - ZOOMED_HALF_LINE_WIDTH, -HALF_HEIGHT],
+      [ZOOMED_HALF_LINE_WIDTH, ZOOMED_HALF_LINE_WIDTH],
+      [
+        -HORIZONTAL_LINE_LENGTH + ZOOMED_HALF_LINE_WIDTH,
+        ZOOMED_HALF_LINE_WIDTH,
+      ],
+      [0, 0],
+      [0, VERTICAL_LINE_LENGTH],
     ],
     [
-      [-halfWidth, halfHeight],
-      [0, -halfLineWidth],
-      [length, -halfLineWidth],
-      [halfLineWidth, 0],
-      [halfLineWidth, -length + halfLineWidth],
+      [-HALF_WIDTH, HALF_HEIGHT],
+      [0, -ZOOMED_HALF_LINE_WIDTH],
+      [HORIZONTAL_LINE_LENGTH, -ZOOMED_HALF_LINE_WIDTH],
+      [ZOOMED_HALF_LINE_WIDTH, 0],
+      [ZOOMED_HALF_LINE_WIDTH, -VERTICAL_LINE_LENGTH],
     ],
     [
-      [halfWidth - halfLineWidth, halfHeight - halfLineWidth],
-      [halfLineWidth, 0],
-      [-length + halfLineWidth, 0],
-      [0, halfLineWidth],
-      [0, -length + lineWidth],
+      [HALF_WIDTH - ZOOMED_HALF_LINE_WIDTH, HALF_HEIGHT],
+      [ZOOMED_HALF_LINE_WIDTH, -ZOOMED_HALF_LINE_WIDTH],
+      [
+        -HORIZONTAL_LINE_LENGTH + ZOOMED_HALF_LINE_WIDTH,
+        -ZOOMED_HALF_LINE_WIDTH,
+      ],
+      [0, 0],
+      [0, -VERTICAL_LINE_LENGTH],
     ],
   ];
 
@@ -871,18 +889,7 @@ const _renderInteractiveScene = ({
       // Optimisation for finding quickly relevant element ids
       const locallySelectedIds = arrayToMap(selectedElements);
 
-      const selections: {
-        angle: number;
-        elementX1: number;
-        elementY1: number;
-        elementX2: number;
-        elementY2: number;
-        selectionColors: string[];
-        dashed?: boolean;
-        cx: number;
-        cy: number;
-        activeEmbeddable: boolean;
-      }[] = [];
+      const selections: ElementSelectionBorder[] = [];
 
       for (const element of elementsMap.values()) {
         const selectionColors = [];
@@ -922,14 +929,17 @@ const _renderInteractiveScene = ({
         }
 
         if (selectionColors.length) {
-          const [elementX1, elementY1, elementX2, elementY2, cx, cy] =
-            getElementAbsoluteCoords(element, elementsMap, true);
+          const [x1, y1, x2, y2, cx, cy] = getElementAbsoluteCoords(
+            element,
+            elementsMap,
+            true,
+          );
           selections.push({
             angle: element.angle,
-            elementX1,
-            elementY1,
-            elementX2,
-            elementY2,
+            x1,
+            y1,
+            x2,
+            y2,
             selectionColors,
             dashed: !!remoteClients,
             cx,
@@ -937,24 +947,25 @@ const _renderInteractiveScene = ({
             activeEmbeddable:
               appState.activeEmbeddable?.element === element &&
               appState.activeEmbeddable.state === "active",
+            padding:
+              element.id === appState.croppingElement?.id ? 0 : undefined,
           });
         }
       }
 
       const addSelectionForGroupId = (groupId: GroupId) => {
         const groupElements = getElementsInGroup(elementsMap, groupId);
-        const [elementX1, elementY1, elementX2, elementY2] =
-          getCommonBounds(groupElements);
+        const [x1, y1, x2, y2] = getCommonBounds(groupElements);
         selections.push({
           angle: 0,
-          elementX1,
-          elementX2,
-          elementY1,
-          elementY2,
+          x1,
+          x2,
+          y1,
+          y2,
           selectionColors: [oc.black],
           dashed: true,
-          cx: elementX1 + (elementX2 - elementX1) / 2,
-          cy: elementY1 + (elementY2 - elementY1) / 2,
+          cx: x1 + (x2 - x1) / 2,
+          cy: y1 + (y2 - y1) / 2,
           activeEmbeddable: false,
         });
       };