|
|
@@ -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,
|
|
|
}
|
|
|
);
|
|
|
}
|