From ee58ae4a222598436549949f3486929ddac0854d Mon Sep 17 00:00:00 2001 From: wangxiaoshuang <825034831@qq.com> Date: Fri, 14 Aug 2026 15:47:44 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9D=9Edicom=E5=BD=B1=E5=83=8F=E9=98=85?= =?UTF-8?q?=E7=89=87=E5=A4=A7=E5=B0=8F=E4=B8=8D=E5=AF=B9=E3=80=81=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E7=A7=BB=E5=8A=A8=E9=97=AE=E9=A2=98=E8=A7=A3=E5=86=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dicoms/components/NoneDicomsCanvas.vue | 89 ++++++++++++++----- 1 file changed, 68 insertions(+), 21 deletions(-) diff --git a/src/views/trials/trials-panel/reading/dicoms/components/NoneDicomsCanvas.vue b/src/views/trials/trials-panel/reading/dicoms/components/NoneDicomsCanvas.vue index 01508b8f..88baa296 100644 --- a/src/views/trials/trials-panel/reading/dicoms/components/NoneDicomsCanvas.vue +++ b/src/views/trials/trials-panel/reading/dicoms/components/NoneDicomsCanvas.vue @@ -137,6 +137,7 @@ export default { currentDrawData: {}, canvasData: [], imgZoom: 1, + isDragging: false, isToolDisabled: false, lesionName: '', visitTaskId: '', @@ -209,6 +210,10 @@ export default { } this.deviceSupportInstall() }, + beforeDestroy() { + window.removeEventListener('message', this.receiveMsg) + this.stopDragging() + }, methods: { getCanvasData() { return new Promise(async resolve => { @@ -337,25 +342,55 @@ export default { // 初始化画布 initCanvas(img) { this.loading = true - this.canvasSize.height = img.height - this.canvasSize.width = img.width - this.imgSize.height = img.height this.imgSize.width = img.width const canvasDiv = document.getElementsByClassName('image-viewer__canvas')[0] + const widthRatio = canvasDiv && canvasDiv.offsetWidth ? canvasDiv.offsetWidth / img.width : 1 + const heightRatio = canvasDiv && canvasDiv.offsetHeight ? canvasDiv.offsetHeight / img.height : 1 + this.imgZoom = Math.min(widthRatio, heightRatio, 1) + this.canvasSize.height = Math.round(img.height * this.imgZoom) + this.canvasSize.width = Math.round(img.width * this.imgZoom) this.canvasPosition = { - x: canvasDiv.offsetWidth / 2 - img.width / 2, - y: canvasDiv.offsetHeight / 2 - img.height / 2 - 25 + x: canvasDiv.offsetWidth / 2 - this.canvasSize.width / 2, + y: canvasDiv.offsetHeight / 2 - this.canvasSize.height / 2 - 25 } // 背景居中 this.$nextTick(async () => { ctx = document.getElementById('canvas').getContext('2d') // 获取上下文 - await ctx.drawImage(img, 0, 0, img.width, img.height) // 在canvas中绘制图片(图片、起始位置、绘图尺寸) + await ctx.drawImage(img, 0, 0, this.canvasSize.width, this.canvasSize.height) // 在canvas中绘制图片(图片、起始位置、绘图尺寸) this.drawToArr() this.loading = false }) }, + scalePoint(point) { + return { + x: point.x * this.imgZoom, + y: point.y * this.imgZoom + } + }, + startDragging(e) { + const { offsetX, offsetY } = this.transform + const startX = e.pageX + const startY = e.pageY + this.isDragging = true + this._dragHandler = rafThrottle((ev) => { + this.transform.offsetX = offsetX + ev.pageX - startX + this.transform.offsetY = offsetY + ev.pageY - startY + }) + this._dragEndHandler = () => { + this.stopDragging() + } + on(document, 'mousemove', this._dragHandler) + on(document, 'mouseup', this._dragEndHandler) + }, + stopDragging() { + off(document, 'mousemove', this._dragHandler) + off(document, 'mouseup', this._dragEndHandler) + this._dragHandler = null + this._dragEndHandler = null + this.isDragging = false + }, // 清空画布 clearCanvas() { @@ -381,6 +416,11 @@ export default { if (e.button !== 0) { return } + if (!this.model) { + this.startDragging(e) + e.preventDefault() + return + } this.isMouseDown = true // 打开鼠标状态 // 获取画布中鼠标开始点击位置 this.canvasMouseStart = { @@ -391,6 +431,9 @@ export default { // 鼠标移动事件 async handleMouseMove(e) { + if (!this.model || this.isDragging) { + return + } // 获取屏幕中鼠标位置(显示实时坐标) this.mousePosition = { x: e.pageX, @@ -437,10 +480,12 @@ export default { var headlen = 10// 自定义箭头线的长度 var theta = 45// 自定义箭头线与直线的夹角 var arrowX, arrowY// 箭头线终点坐标 - var fromX = e.data.handles.start.x - var fromY = e.data.handles.start.y - var toX = e.data.handles.end.x - var toY = e.data.handles.end.y + var start = this.scalePoint(e.data.handles.start) + var end = this.scalePoint(e.data.handles.end) + var fromX = start.x + var fromY = start.y + var toX = end.x + var toY = end.y // 计算各角度和对应的箭头终点坐标 var angle = Math.atan2(fromY - toY, fromX - toX) * 180 / Math.PI var angle1 = (angle + theta) * Math.PI / 180 @@ -453,8 +498,8 @@ export default { // 画直线 ctx.lineWidth = this.lineWidth ctx.beginPath() - ctx.moveTo(fromX * this.imgZoom, fromY * this.imgZoom) - ctx.lineTo(toX * this.imgZoom, toY * this.imgZoom) + ctx.moveTo(fromX, fromY) + ctx.lineTo(toX, toY) arrowX = toX + topX arrowY = toY + topY @@ -473,18 +518,16 @@ export default { ctx.lineWidth = this.lineWidth ctx.beginPath() ctx.strokeStyle = this.color + const start = this.scalePoint(e.data.handles.start) + const end = this.scalePoint(e.data.handles.end) // 绘制矩形边框 ctx.strokeRect( - // this.canvasMouseStart.x, - // this.canvasMouseStart.y, - // e.offsetX - this.canvasMouseStart.x, - // e.offsetY - this.canvasMouseStart.y - e.data.handles.start.x, - e.data.handles.start.y, - e.data.handles.end.x - e.data.handles.start.x, - e.data.handles.end.y - e.data.handles.start.y + start.x, + start.y, + end.x - start.x, + end.y - start.y ) - this.drawText(ctx, { x: e.data.handles.start.x, y: e.data.handles.start.y }, { x: e.data.handles.end.x, y: e.data.handles.end.y }, e.data.remark, this.color) + this.drawText(ctx, start, end, e.data.remark, this.color) } } }) @@ -495,6 +538,10 @@ export default { if (e.button !== 0) { return // 非左键松开 } + if (this.isDragging) { + this.stopDragging() + return + } // 左键松开 if (this.model === 'ArrowAnnotate' || this.model === 'RectangleRoi') {