Jelajahi Sumber

使dara tool可选中

sw 1 bulan lalu
induk
melakukan
6cad5069ea
1 mengubah file dengan 266 tambahan dan 33 penghapusan
  1. 266 33
      src/components/measures/DARAMeasurementTool.ts

+ 266 - 33
src/components/measures/DARAMeasurementTool.ts

@@ -95,6 +95,8 @@ interface DARAMeasurementAnnotation extends Types.Annotation {
       };
     };
   };
+  // 添加选中状态字段
+  // selected?: boolean; //父类里面已经定义 isSelected
 }
 
 // 导出的注解数据接口
@@ -137,6 +139,12 @@ export default class DARAMeasurementTool extends AnnotationTool {
     textBoxBeingMoved?: 'C' | 'D';
     // 记录鼠标点击位置相对于文本框左上角的偏移量,用于防止拖拽时跳跃
     textBoxOffset?: CoreTypes.Point2;
+    // 是否移动整个工具
+    movingWholeTool?: boolean;
+    // 移动整个工具时的初始偏移量
+    wholeToolOffset?: CoreTypes.Point2;
+    // 是否为选中状态(点击线段后进入选中状态)
+    selected?: boolean;
   } | null = null;
 
   isDrawing: boolean = false;
@@ -288,10 +296,10 @@ export default class DARAMeasurementTool extends AnnotationTool {
         textBoxRight: annotation.data.handles.textBoxRight,
       },
       metadata: {
-        viewPlaneNormal: annotation.metadata?.viewPlaneNormal || [0, 0, 1],
-        viewUp: annotation.metadata?.viewUp || [0, 1, 0],
-        FrameOfReferenceUID: annotation.metadata?.FrameOfReferenceUID || '',
-        referencedImageId: annotation.metadata?.referencedImageId || '',
+        viewPlaneNormal: annotation.metadata.viewPlaneNormal || [0, 0, 1],
+        viewUp: annotation.metadata.viewUp || [0, 1, 0],
+        FrameOfReferenceUID: annotation.metadata.FrameOfReferenceUID || '',
+        referencedImageId: annotation.metadata.referencedImageId || '',
       },
     };
   }
@@ -580,6 +588,7 @@ export default class DARAMeasurementTool extends AnnotationTool {
    * 激活绘制模式
    */
   _activateDraw(element: HTMLDivElement): void {
+    console.log(`_activateDraw 被调用`);
     element.addEventListener(
       'CORNERSTONE_TOOLS_MOUSE_DRAG',
       this._dragCallback as EventListener
@@ -598,6 +607,7 @@ export default class DARAMeasurementTool extends AnnotationTool {
    * 取消激活绘制模式
    */
   _deactivateDraw(element: HTMLDivElement): void {
+    console.log(`_deactivateDraw 被调用`);
     element.removeEventListener(
       'CORNERSTONE_TOOLS_MOUSE_DRAG',
       this._dragCallback as EventListener
@@ -616,6 +626,7 @@ export default class DARAMeasurementTool extends AnnotationTool {
    * 激活修改模式
    */
   _activateModify(element: HTMLDivElement): void {
+    console.log(`_activateModify 被调用`);
     element.addEventListener(
       'CORNERSTONE_TOOLS_MOUSE_DOWN',
       this._mouseDownModifyCallback as EventListener
@@ -628,12 +639,17 @@ export default class DARAMeasurementTool extends AnnotationTool {
       'CORNERSTONE_TOOLS_MOUSE_UP',
       this._mouseUpModifyCallback as EventListener
     );
+    element.addEventListener(
+      'CORNERSTONE_TOOLS_MOUSE_MOVE',
+      this._mouseMoveModifyCallback as EventListener
+    );
   }
 
   /**
    * 取消激活修改模式
    */
   _deactivateModify(element: HTMLDivElement): void {
+    console.log(`_deactivateModify 被调用`);
     element.removeEventListener(
       'CORNERSTONE_TOOLS_MOUSE_DOWN',
       this._mouseDownModifyCallback as EventListener
@@ -646,8 +662,118 @@ export default class DARAMeasurementTool extends AnnotationTool {
       'CORNERSTONE_TOOLS_MOUSE_UP',
       this._mouseUpModifyCallback as EventListener
     );
+    element.removeEventListener(
+      'CORNERSTONE_TOOLS_MOUSE_MOVE',
+      this._mouseMoveModifyCallback as EventListener
+    );
   }
 
+  /**
+   * 鼠标移动回调 - 用于修改模式,处理悬停检测
+   * 实现功能1和2:鼠标悬停在文本上时光标为手型,悬停在线段或手柄上时光标为十字准星
+   */
+  _mouseMoveModifyCallback = (evt: EventTypes.InteractionEventType): void => {
+    const eventDetail = evt.detail;
+    const { element, currentPoints } = eventDetail;
+    // 添加空值检查
+    if (!currentPoints || !currentPoints.canvas) {
+      return;
+    }
+    const canvasCoords = currentPoints.canvas;
+
+    const enabledElement = getEnabledElement(element);
+    if (!enabledElement) {
+      return;
+    }
+    const { viewport } = enabledElement;
+
+    const annotations = annotation.state.getAnnotations(this.getToolName(), element);
+    if (!annotations || annotations.length === 0) {
+      // 没有注解时,重置光标
+      element.style.cursor = 'default';
+      return;
+    }
+
+    let isHovering = false;
+
+    // 检查是否悬停在文本框上
+    for (const ann of annotations) {
+      const customAnn = ann as DARAMeasurementAnnotation;
+      const targetId = this.getTargetId(viewport);
+      const cachedStats = targetId ? customAnn.data.cachedStats?.[targetId] : undefined;
+
+      if (cachedStats?.leftIntersection) {
+        const intersectionCanvas = viewport.worldToCanvas(cachedStats.leftIntersection);
+        const textBoxC: CoreTypes.Point2 = customAnn.data.handles.textBoxLeft || [
+          intersectionCanvas[0] + 10,
+          intersectionCanvas[1] - 10,
+        ];
+
+        if (this._isPointInTextBox(canvasCoords, textBoxC)) {
+          element.style.cursor = 'pointer'; // 手型光标
+          customAnn.highlighted = true;
+          isHovering = true;
+          break;
+        }
+      }
+
+      if (cachedStats?.rightIntersection) {
+        const intersectionDCanvas = viewport.worldToCanvas(cachedStats.rightIntersection);
+        const textBoxD: CoreTypes.Point2 = customAnn.data.handles.textBoxRight || [
+          intersectionDCanvas[0] + 10,
+          intersectionDCanvas[1] + 20,
+        ];
+
+        if (this._isPointInTextBox(canvasCoords, textBoxD)) {
+          element.style.cursor = 'pointer'; // 手型光标
+          customAnn.highlighted = true;
+          isHovering = true;
+          break;
+        }
+      }
+    }
+
+    // 如果没有悬停在文本框上,检查是否悬停在手柄或线段上
+    if (!isHovering) {
+      for (const ann of annotations) {
+        const customAnn = ann as DARAMeasurementAnnotation;
+
+        // 检查是否靠近手柄
+        const handle = this.getHandleNearImagePoint(element, customAnn, canvasCoords, 6);
+        if (handle) {
+          element.style.cursor = 'crosshair'; // 十字准星光标
+          customAnn.highlighted = true;
+          isHovering = true;
+          break;
+        }
+
+        // 检查是否靠近线段
+        if (this.isPointNearTool(element, customAnn, canvasCoords, 10)) {
+          element.style.cursor = 'crosshair'; // 十字准星光标
+          customAnn.highlighted = true;
+          isHovering = true;
+          break;
+        }
+      }
+    }
+
+    // 如果没有悬停在任何地方,重置高亮和光标
+    if (!isHovering) {
+      for (const ann of annotations) {
+        const customAnn = ann as DARAMeasurementAnnotation;
+        customAnn.highlighted = false;
+      }
+      element.style.cursor = 'default';
+    }
+
+    // 触发渲染以更新高亮状态
+    const viewportIdsToRender = utilities.viewportFilters.getViewportIdsWithToolToRender(
+      element,
+      this.getToolName()
+    );
+    utilities.triggerAnnotationRenderForViewportIds(viewportIdsToRender);
+  };
+
   /**
    * 鼠标按下回调 - 用于修改模式
    */
@@ -712,10 +838,12 @@ export default class DARAMeasurementTool extends AnnotationTool {
             hasMoved: false,
             textBoxBeingMoved: 'C',
             textBoxOffset: textBoxOffset, // 保存偏移量
+            //selected:this.editData?.selected || false,
           };
 
-          customAnn.highlighted = true;
-          utilities.triggerAnnotationRenderForViewportIds(viewportIdsToRender);
+          // 注释:移除立即设置 highlighted,改为在释放时判断
+          // customAnn.highlighted = true;
+          // utilities.triggerAnnotationRenderForViewportIds(viewportIdsToRender);
 
           evt.preventDefault();
           evt.stopPropagation();
@@ -751,6 +879,7 @@ export default class DARAMeasurementTool extends AnnotationTool {
             hasMoved: false,
             textBoxBeingMoved: 'D',
             textBoxOffset: textBoxOffset, // 保存偏移量
+            //selected:this.editData?.selected || false,
           };
 
           customAnn.highlighted = true;
@@ -799,6 +928,65 @@ export default class DARAMeasurementTool extends AnnotationTool {
         return;
       }
     }
+
+    // 如果没有找到手柄,检查是否点击在工具的其他位置(线段上)
+    for (const ann of annotations) {
+      const customAnn = ann as DARAMeasurementAnnotation;
+      if (this.isPointNearTool(element, customAnn, canvasCoords, 10)) {
+        // 点击在线段上,开始移动整个工具
+        const viewportIdsToRender =
+          utilities.viewportFilters.getViewportIdsWithToolToRender(
+            element,
+            this.getToolName()
+          );
+
+        // 计算鼠标点击位置相对于工具的偏移量
+        const points = customAnn.data.handles.points;
+        if (points.length >= 8) {
+          const midPoint = calculateMidpoint(points[0], points[1]);
+          const midCanvas = viewport.worldToCanvas(midPoint);
+          const wholeToolOffset: CoreTypes.Point2 = [
+            canvasCoords[0] - midCanvas[0],
+            canvasCoords[1] - midCanvas[1],
+          ];
+
+          this.editData = {
+            annotation: customAnn,
+            viewportIdsToRender,
+            hasMoved: false,
+            movingWholeTool: true,
+            wholeToolOffset: wholeToolOffset,
+            //selected:this.editData?.selected || false,
+          };
+
+          customAnn.highlighted = true;
+
+          utilities.triggerAnnotationRenderForViewportIds(
+            viewportIdsToRender
+          );
+
+          evt.preventDefault();
+          evt.stopPropagation();
+          return;
+        }
+      }
+    }
+
+    // 如果没有点击在工具上,取消所有工具的选中状态
+    for (const ann of annotations) {
+      const customAnn = ann as DARAMeasurementAnnotation;
+      customAnn.highlighted = false;
+    }
+
+    const viewportIdsToRender =
+      utilities.viewportFilters.getViewportIdsWithToolToRender(
+        element,
+        this.getToolName()
+      );
+
+    utilities.triggerAnnotationRenderForViewportIds(
+      viewportIdsToRender
+    );
   };
 
   /**
@@ -818,7 +1006,7 @@ export default class DARAMeasurementTool extends AnnotationTool {
       return;
     }
 
-    const { annotation: ann, viewportIdsToRender, textBoxBeingMoved } = this.editData;
+    const { annotation: ann, viewportIdsToRender, textBoxBeingMoved, movingWholeTool } = this.editData;
     const customAnn = ann as DARAMeasurementAnnotation;
     const { data } = customAnn;
 
@@ -849,6 +1037,56 @@ export default class DARAMeasurementTool extends AnnotationTool {
       return;
     }
 
+    // 如果正在移动整个工具
+    if (movingWholeTool && this.editData.wholeToolOffset) {
+      // 计算新的中点位置
+      const newMidCanvas: CoreTypes.Point2 = [
+        canvasCoords[0] - this.editData.wholeToolOffset[0],
+        canvasCoords[1] - this.editData.wholeToolOffset[1],
+      ];
+      const newMidWorld = enabledElement.viewport.canvasToWorld(newMidCanvas);
+
+      // 计算所有点的偏移量
+      const points = data.handles.points;
+      if (points.length >= 8) {
+        const oldMid = calculateMidpoint(points[0], points[1]);
+        const offset = vectorSubtract(newMidWorld, oldMid);
+
+        // 移动所有点
+        for (let i = 0; i < points.length; i++) {
+          points[i] = vectorAdd(points[i], offset);
+        }
+
+        // 移动文本框位置(使用相同的偏移量)
+        if (data.handles.textBoxLeft) {
+          data.handles.textBoxLeft = [
+            data.handles.textBoxLeft[0] + offset[0],
+            data.handles.textBoxLeft[1] + offset[1]
+          ];
+        }
+        if (data.handles.textBoxRight) {
+          data.handles.textBoxRight = [
+            data.handles.textBoxRight[0] + offset[0],
+            data.handles.textBoxRight[1] + offset[1]
+          ];
+        }
+
+        // 重新计算角度
+        this._updateCachedStats(customAnn, enabledElement);
+
+        this.editData.hasMoved = true;
+
+        // 触发渲染更新
+        utilities.triggerAnnotationRenderForViewportIds(
+          viewportIdsToRender
+        );
+
+        evt.preventDefault();
+        evt.stopPropagation();
+        return;
+      }
+    }
+
     // 否则处理手柄拖拽
     const worldPos = currentPoints.world;
     const activeHandleIndex = data.handles.activeHandleIndex;
@@ -876,16 +1114,26 @@ export default class DARAMeasurementTool extends AnnotationTool {
    * 鼠标释放回调 - 用于修改模式
    */
   _mouseUpModifyCallback = (evt: EventTypes.InteractionEventType): void => {
+    console.log(`进入 _mouseUpModifyCallback`)
     if (!this.editData) {
       return;
     }
 
-    const { annotation: ann } = this.editData;
+    const { annotation: ann, hasMoved, movingWholeTool } = this.editData;
     const customAnn = ann as DARAMeasurementAnnotation;
 
     // 清除active状态
     customAnn.data.handles.activeHandleIndex = null;
-    customAnn.highlighted = false;
+
+    console.log(`hasMoved是 ${hasMoved}`)
+    // 如果没有拖拽且点击在线段上(movingWholeTool为true),则进入选中状态
+    if (!hasMoved && movingWholeTool) {
+      // 设置选中状态:使用注解的selected字段
+      console.log(`鼠标弹起,选中了。hasMoved是 ${hasMoved}`)
+      customAnn.highlighted = true; // 保持高亮以显示选中
+    } else {
+      customAnn.highlighted = false;
+    }
 
     const eventDetail = evt.detail;
     const { element } = eventDetail;
@@ -907,34 +1155,12 @@ export default class DARAMeasurementTool extends AnnotationTool {
   };
 
   /**
-   * 处理选中回调
+   * 处理 控制点/端点 选中回调
    */
   handleSelectedCallback(
     evt: EventTypes.InteractionEventType,
     annotation: DARAMeasurementAnnotation
   ): void {
-    const eventDetail = evt.detail;
-    const { element } = eventDetail;
-
-    annotation.highlighted = true;
-
-    const enabledElement = getEnabledElement(element);
-    if (!enabledElement) {
-      return;
-    }
-    const { renderingEngine } = enabledElement;
-    const viewportIdsToRender =
-      utilities.viewportFilters.getViewportIdsWithToolToRender(
-        element,
-        this.getToolName()
-      );
-
-    utilities.triggerAnnotationRenderForViewportIds(
-      //renderingEngine,
-      viewportIdsToRender
-    );
-
-    evt.preventDefault();
   }
 
   /**
@@ -945,6 +1171,9 @@ export default class DARAMeasurementTool extends AnnotationTool {
     annotation: DARAMeasurementAnnotation
   ): void {
     // 实现工具选中逻辑
+    console.log(`选中了dara`);
+    // if(this.editData)
+    //   this.editData.selected=true;
   }
 
   /**
@@ -1619,6 +1848,10 @@ export default class DARAMeasurementTool extends AnnotationTool {
       // 绘制手柄点
       if (annotationUID) {
         const handleGroupUID = '0';
+        // 根据选中状态调整手柄半径:选中时为12,否则为8
+        console.log(`${this.editData?.selected}--${annotation.isSelected}--${annotation.highlighted}`);
+        const isSelected = this.editData?.selected || annotation.isSelected || annotation.highlighted;
+        const handleRadius = isSelected ? 12 : 8;
         drawHandles(
           svgDrawingHelper,
           annotationUID,
@@ -1626,7 +1859,7 @@ export default class DARAMeasurementTool extends AnnotationTool {
           canvasPoints,
           {
             color: 'rgb(255, 255, 255)',
-            handleRadius: 8,
+            handleRadius: handleRadius,
           }
         );
       }