|
|
@@ -84,6 +84,8 @@ export default class LineGrayscaleMeasurementTool extends AnnotationTool {
|
|
|
hasMoved?: boolean;
|
|
|
textBoxBeingMoved?: boolean;
|
|
|
textBoxOffset?: CoreTypes.Point2;
|
|
|
+ wholeToolOffset?: CoreTypes.Point2;
|
|
|
+ originalPoints?: CoreTypes.Point3[]; // 保存拖拽开始时的原始点坐标
|
|
|
} | null = null;
|
|
|
|
|
|
isDrawing: boolean = false;
|
|
|
@@ -372,9 +374,45 @@ export default class LineGrayscaleMeasurementTool extends AnnotationTool {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // 查找最近的手柄
|
|
|
+ // 查找最近的手柄或工具
|
|
|
for (const ann of annotations) {
|
|
|
const customAnn = ann as LineGrayscaleAnnotation;
|
|
|
+
|
|
|
+ // 1. 检查是否点击在文本框上
|
|
|
+ if (customAnn.data.textBox) {
|
|
|
+ const textBoxCanvas = customAnn.data.textBox;
|
|
|
+ if (this._isPointNearTextBox(canvasCoords, textBoxCanvas)) {
|
|
|
+ const viewportIdsToRender =
|
|
|
+ utilities.viewportFilters.getViewportIdsWithToolToRender(
|
|
|
+ element,
|
|
|
+ this.getToolName()
|
|
|
+ );
|
|
|
+
|
|
|
+ this.editData = {
|
|
|
+ annotation: customAnn,
|
|
|
+ viewportIdsToRender,
|
|
|
+ textBoxBeingMoved: true,
|
|
|
+ textBoxOffset: [
|
|
|
+ canvasCoords[0] - textBoxCanvas[0],
|
|
|
+ canvasCoords[1] - textBoxCanvas[1],
|
|
|
+ ],
|
|
|
+ hasMoved: false,
|
|
|
+ };
|
|
|
+
|
|
|
+ customAnn.isSelected = true;
|
|
|
+ customAnn.highlighted = true;
|
|
|
+
|
|
|
+ utilities.triggerAnnotationRenderForViewportIds(
|
|
|
+ viewportIdsToRender
|
|
|
+ );
|
|
|
+
|
|
|
+ evt.preventDefault();
|
|
|
+ evt.stopPropagation();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 检查是否点击在手柄上
|
|
|
const handle = this.getHandleNearImagePoint(
|
|
|
element,
|
|
|
customAnn,
|
|
|
@@ -394,6 +432,50 @@ export default class LineGrayscaleMeasurementTool extends AnnotationTool {
|
|
|
viewportIdsToRender,
|
|
|
handleIndex: customAnn.data.handles.activeHandleIndex || 0,
|
|
|
hasMoved: false,
|
|
|
+ originalPoints: [...customAnn.data.handles.points],
|
|
|
+ };
|
|
|
+
|
|
|
+ customAnn.isSelected = true;
|
|
|
+ customAnn.highlighted = true;
|
|
|
+
|
|
|
+ utilities.triggerAnnotationRenderForViewportIds(
|
|
|
+ viewportIdsToRender
|
|
|
+ );
|
|
|
+
|
|
|
+ evt.preventDefault();
|
|
|
+ evt.stopPropagation();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 检查是否点击在线段上(拖拽整个工具)
|
|
|
+ if (this.isPointNearTool(element, customAnn, canvasCoords, 10)) {
|
|
|
+ const viewportIdsToRender =
|
|
|
+ utilities.viewportFilters.getViewportIdsWithToolToRender(
|
|
|
+ element,
|
|
|
+ this.getToolName()
|
|
|
+ );
|
|
|
+
|
|
|
+ // 计算线段中心点
|
|
|
+ const points = customAnn.data.handles.points;
|
|
|
+ const centerWorld: CoreTypes.Point3 = [
|
|
|
+ (points[0][0] + points[1][0]) / 2,
|
|
|
+ (points[0][1] + points[1][1]) / 2,
|
|
|
+ (points[0][2] + points[1][2]) / 2,
|
|
|
+ ];
|
|
|
+ const centerCanvas = viewport.worldToCanvas(centerWorld);
|
|
|
+
|
|
|
+ const wholeToolOffset: CoreTypes.Point2 = [
|
|
|
+ canvasCoords[0] - centerCanvas[0],
|
|
|
+ canvasCoords[1] - centerCanvas[1],
|
|
|
+ ];
|
|
|
+
|
|
|
+ // 开始拖拽整个工具
|
|
|
+ this.editData = {
|
|
|
+ annotation: customAnn,
|
|
|
+ viewportIdsToRender,
|
|
|
+ handleIndex: -1, // -1表示拖拽整个工具
|
|
|
+ hasMoved: false,
|
|
|
+ wholeToolOffset: wholeToolOffset,
|
|
|
};
|
|
|
|
|
|
customAnn.isSelected = true;
|
|
|
@@ -414,6 +496,13 @@ export default class LineGrayscaleMeasurementTool extends AnnotationTool {
|
|
|
const customAnn = ann as LineGrayscaleAnnotation;
|
|
|
customAnn.isSelected = false;
|
|
|
}
|
|
|
+
|
|
|
+ const viewportIdsToRender =
|
|
|
+ utilities.viewportFilters.getViewportIdsWithToolToRender(
|
|
|
+ element,
|
|
|
+ this.getToolName()
|
|
|
+ );
|
|
|
+ utilities.triggerAnnotationRenderForViewportIds(viewportIdsToRender);
|
|
|
};
|
|
|
|
|
|
_mouseDragModifyCallback = (evt: EventTypes.InteractionEventType): void => {
|
|
|
@@ -423,25 +512,89 @@ export default class LineGrayscaleMeasurementTool extends AnnotationTool {
|
|
|
|
|
|
const eventDetail = evt.detail;
|
|
|
const { currentPoints } = eventDetail;
|
|
|
+ const canvasCoords = currentPoints.canvas;
|
|
|
|
|
|
const enabledElement = getEnabledElement(eventDetail.element);
|
|
|
if (!enabledElement) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ const { viewport } = enabledElement;
|
|
|
const { annotation: ann, viewportIdsToRender } = this.editData;
|
|
|
const customAnn = ann as LineGrayscaleAnnotation;
|
|
|
const { data } = customAnn;
|
|
|
|
|
|
- // 处理手柄拖拽
|
|
|
+ // 1. 处理文本框拖拽
|
|
|
+ if (this.editData.textBoxBeingMoved && this.editData.textBoxOffset) {
|
|
|
+ const newTextBoxPosition: CoreTypes.Point2 = [
|
|
|
+ canvasCoords[0] - this.editData.textBoxOffset[0],
|
|
|
+ canvasCoords[1] - this.editData.textBoxOffset[1],
|
|
|
+ ];
|
|
|
+
|
|
|
+ data.textBox = newTextBoxPosition;
|
|
|
+ this.editData.hasMoved = true;
|
|
|
+
|
|
|
+ utilities.triggerAnnotationRenderForViewportIds(
|
|
|
+ viewportIdsToRender
|
|
|
+ );
|
|
|
+
|
|
|
+ evt.preventDefault();
|
|
|
+ evt.stopPropagation();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 处理整个工具的平移
|
|
|
+ if (this.editData.handleIndex === -1 && this.editData.wholeToolOffset) {
|
|
|
+ // 计算新的中心位置
|
|
|
+ const newCenterCanvas: CoreTypes.Point2 = [
|
|
|
+ canvasCoords[0] - this.editData.wholeToolOffset[0],
|
|
|
+ canvasCoords[1] - this.editData.wholeToolOffset[1],
|
|
|
+ ];
|
|
|
+
|
|
|
+ const newCenterWorld = viewport.canvasToWorld(newCenterCanvas);
|
|
|
+
|
|
|
+ // 计算当前中心位置
|
|
|
+ const points = data.handles.points;
|
|
|
+ const currentCenterWorld: CoreTypes.Point3 = [
|
|
|
+ (points[0][0] + points[1][0]) / 2,
|
|
|
+ (points[0][1] + points[1][1]) / 2,
|
|
|
+ (points[0][2] + points[1][2]) / 2,
|
|
|
+ ];
|
|
|
+
|
|
|
+ // 计算偏移量
|
|
|
+ const worldOffset: CoreTypes.Point3 = [
|
|
|
+ newCenterWorld[0] - currentCenterWorld[0],
|
|
|
+ newCenterWorld[1] - currentCenterWorld[1],
|
|
|
+ 0,
|
|
|
+ ];
|
|
|
+
|
|
|
+ // 应用偏移到所有点
|
|
|
+ for (let i = 0; i < data.handles.points.length; i++) {
|
|
|
+ data.handles.points[i] = [
|
|
|
+ data.handles.points[i][0] + worldOffset[0],
|
|
|
+ data.handles.points[i][1] + worldOffset[1],
|
|
|
+ data.handles.points[i][2],
|
|
|
+ ] as CoreTypes.Point3;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.editData.hasMoved = true;
|
|
|
+
|
|
|
+ utilities.triggerAnnotationRenderForViewportIds(
|
|
|
+ viewportIdsToRender
|
|
|
+ );
|
|
|
+
|
|
|
+ evt.preventDefault();
|
|
|
+ evt.stopPropagation();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 处理手柄拖拽
|
|
|
const worldPos = currentPoints.world;
|
|
|
const activeHandleIndex = data.handles.activeHandleIndex;
|
|
|
|
|
|
if (activeHandleIndex !== null && activeHandleIndex >= 0 && activeHandleIndex < data.handles.points.length) {
|
|
|
data.handles.points[activeHandleIndex] = worldPos;
|
|
|
|
|
|
- this._updateCachedStats(customAnn, enabledElement);
|
|
|
-
|
|
|
this.editData.hasMoved = true;
|
|
|
|
|
|
utilities.triggerAnnotationRenderForViewportIds(
|
|
|
@@ -458,7 +611,7 @@ export default class LineGrayscaleMeasurementTool extends AnnotationTool {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- const { annotation: ann } = this.editData;
|
|
|
+ const { annotation: ann, hasMoved } = this.editData;
|
|
|
const customAnn = ann as LineGrayscaleAnnotation;
|
|
|
|
|
|
customAnn.data.handles.activeHandleIndex = null;
|
|
|
@@ -467,6 +620,13 @@ export default class LineGrayscaleMeasurementTool extends AnnotationTool {
|
|
|
const eventDetail = evt.detail;
|
|
|
const { element } = eventDetail;
|
|
|
|
|
|
+ const enabledElement = getEnabledElement(element);
|
|
|
+
|
|
|
+ // 如果工具被移动了,更新缓存的统计数据
|
|
|
+ if (hasMoved && enabledElement && !this.editData.textBoxBeingMoved) {
|
|
|
+ this._updateCachedStats(customAnn, enabledElement);
|
|
|
+ }
|
|
|
+
|
|
|
const viewportIdsToRender =
|
|
|
utilities.viewportFilters.getViewportIdsWithToolToRender(
|
|
|
element,
|
|
|
@@ -504,25 +664,40 @@ export default class LineGrayscaleMeasurementTool extends AnnotationTool {
|
|
|
}
|
|
|
|
|
|
let isHovering = false;
|
|
|
+ let cursorSet = false;
|
|
|
|
|
|
- // 检查是否悬停在手柄或直线上
|
|
|
+ // 检查是否悬停在文本、手柄或直线上
|
|
|
for (const ann of annotations) {
|
|
|
const customAnn = ann as LineGrayscaleAnnotation;
|
|
|
|
|
|
- // 检查是否靠近手柄
|
|
|
+ // 1. 检查是否悬停在文本框上
|
|
|
+ if (customAnn.data.textBox) {
|
|
|
+ const textBoxCanvas = customAnn.data.textBox;
|
|
|
+ if (this._isPointNearTextBox(canvasCoords, textBoxCanvas)) {
|
|
|
+ element.style.cursor = 'pointer';
|
|
|
+ customAnn.highlighted = true;
|
|
|
+ isHovering = true;
|
|
|
+ cursorSet = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 检查是否靠近手柄
|
|
|
const handle = this.getHandleNearImagePoint(element, customAnn, canvasCoords, 6);
|
|
|
if (handle) {
|
|
|
element.style.cursor = 'crosshair';
|
|
|
customAnn.highlighted = true;
|
|
|
isHovering = true;
|
|
|
+ cursorSet = true;
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- // 检查是否靠近直线
|
|
|
+ // 3. 检查是否靠近直线
|
|
|
if (this.isPointNearTool(element, customAnn, canvasCoords, 10)) {
|
|
|
element.style.cursor = 'crosshair';
|
|
|
customAnn.highlighted = true;
|
|
|
isHovering = true;
|
|
|
+ cursorSet = true;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
@@ -531,7 +706,9 @@ export default class LineGrayscaleMeasurementTool extends AnnotationTool {
|
|
|
if (!isHovering) {
|
|
|
for (const ann of annotations) {
|
|
|
const customAnn = ann as LineGrayscaleAnnotation;
|
|
|
- customAnn.highlighted = false;
|
|
|
+ if (!customAnn.isSelected) {
|
|
|
+ customAnn.highlighted = false;
|
|
|
+ }
|
|
|
}
|
|
|
element.style.cursor = 'default';
|
|
|
}
|
|
|
@@ -645,6 +822,26 @@ export default class LineGrayscaleMeasurementTool extends AnnotationTool {
|
|
|
return undefined;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 检查点是否靠近文本框
|
|
|
+ */
|
|
|
+ private _isPointNearTextBox(
|
|
|
+ point: CoreTypes.Point2,
|
|
|
+ textBoxPosition: CoreTypes.Point2,
|
|
|
+ padding: number = 50
|
|
|
+ ): boolean {
|
|
|
+ // 简单的矩形碰撞检测,假设文本框大小约为 150x80
|
|
|
+ const textBoxWidth = 150;
|
|
|
+ const textBoxHeight = 80;
|
|
|
+
|
|
|
+ return (
|
|
|
+ point[0] >= textBoxPosition[0] - padding &&
|
|
|
+ point[0] <= textBoxPosition[0] + textBoxWidth + padding &&
|
|
|
+ point[1] >= textBoxPosition[1] - padding &&
|
|
|
+ point[1] <= textBoxPosition[1] + textBoxHeight + padding
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 更新缓存的统计数据
|
|
|
*/
|
|
|
@@ -891,8 +1088,9 @@ export default class LineGrayscaleMeasurementTool extends AnnotationTool {
|
|
|
}
|
|
|
);
|
|
|
|
|
|
- // 绘制手柄
|
|
|
+ // 绘制手柄 - 选中时使用更大的半径
|
|
|
const handleGroupUID = `${annotationUID}-handles`;
|
|
|
+ const handleRadius = annotationItem.isSelected ? 12 : 6;
|
|
|
drawHandles(
|
|
|
svgDrawingHelper,
|
|
|
annotationUID,
|
|
|
@@ -900,6 +1098,7 @@ export default class LineGrayscaleMeasurementTool extends AnnotationTool {
|
|
|
canvasCoordinates,
|
|
|
{
|
|
|
color,
|
|
|
+ handleRadius,
|
|
|
}
|
|
|
);
|
|
|
|
|
|
@@ -934,4 +1133,4 @@ export default class LineGrayscaleMeasurementTool extends AnnotationTool {
|
|
|
return true;
|
|
|
};
|
|
|
|
|
|
-}
|
|
|
+}
|