修复放大功能

This commit is contained in:
Euni4U 2024-12-27 17:03:36 +08:00
parent 31c40d68f6
commit 11ba37fc4c
3 changed files with 142 additions and 87 deletions

View File

@ -146,7 +146,7 @@
</el-button>
<span style="font-size: 15px; margin-bottom: 10px">测量</span>
<!-- <el-button
<el-button
style="width: 30px; height: 30px; margin-bottom: 10px"
type="primary"
plain
@ -154,7 +154,7 @@
>
<el-icon><ZoomIn /></el-icon>
</el-button>
<span style="font-size: 15px; margin-bottom: 10px">放大</span> -->
<span style="font-size: 15px; margin-bottom: 10px">放大</span>
<el-button
style="width: 30px; height: 30px; margin-bottom: 10px"
@ -582,6 +582,7 @@ import ECGCopmareDialog from '@/views/ECG/ECGCompare.vue'
import ECGApplyforRepair from '@/views/ECG/ECGModify/ECGApplyforRepair.vue'
import useClipboard from "vue-clipboard3";//
const { toClipboard } = useClipboard();
import ECGSB from '@/views/ECG/ECGSB.vue'
/** 提交表单 */
const emit = defineEmits(['success']) // success
const message = useMessage() //
@ -965,7 +966,7 @@ function FD() {
const value = IsFD.value === false ? true : false
IsFD.value = value
if (value) {
message.alertSuccess('开启放大')
message.alertSuccess('开启放大')
} else {
message.alertSuccess('关闭放大')
}

View File

@ -1,121 +1,174 @@
<template>
<div class="magnifier" v-show="isShow">
<!-- 只保留放大的内容 -->
<div
v-if="isZoomed"
class="magnifier-glass"
:style="{
left: zoomedPosition.x + 'px',
top: zoomedPosition.y + 'px',
backgroundImage: screenshotUrl ? `url(${screenshotUrl})` : 'none',
backgroundPosition: 'center',
backgroundSize: 'cover',
width: '250px',
height: '250px'
transform: `translate(-50%, -50%) scale(1)`,
width: '300px',
height: '200px',
backgroundColor: 'white'
}"
></div>
>
<canvas ref="magnifierCanvas" width="300" height="200"></canvas>
</div>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
import html2canvas from 'html2canvas'
import ECGForm from './ECGForm.vue'
const isShow = ref(true)
const isZoomed = ref(false)
const screenshotUrl = ref('')
const magnifierCanvas = ref(null)
const zoomLevel = 1.8
const zoomedPosition = reactive({
x: 0,
y: 0
})
//
async function captureArea(x, y) {
try {
const container = document.querySelector('.el-tab-pane')
if (!container) return
const captureSize = 50
const rect = container.getBoundingClientRect()
const left = x - captureSize / 2
const top = y - captureSize / 2
const canvas = await html2canvas(document.body, {
useCORS: true,
allowTaint: true,
scale: 3, //
x: left - rect.left, //
y: top - rect.top, //
width: captureSize,
height: captureSize,
backgroundColor: null
})
screenshotUrl.value = canvas.toDataURL('image/jpeg', 0.5)
isZoomed.value = true
zoomedPosition.x = x
zoomedPosition.y = y
} catch (error) {
console.error('截图失败:', error)
//
function drawMagnifiedArea(x, y, container) {
if (!magnifierCanvas.value) return
const ctx = magnifierCanvas.value.getContext('2d', { willReadFrequently: true })
const container1 = document.querySelector('#canvas-container')
const container2 = document.querySelector('#canvas-container1')
const rect1 = container1.getBoundingClientRect()
const rect2 = container2.getBoundingClientRect()
//
const transitionZone = 20 //
const isInTransition = Math.abs(x - rect2.left) < transitionZone
ctx.clearRect(0, 0, 300, 200)
ctx.imageSmoothingEnabled = true
ctx.imageSmoothingQuality = 'high'
if (isInTransition) {
//
const weight2 = (x - (rect2.left - transitionZone)) / (transitionZone * 2)
const weight1 = 1 - weight2
//
drawContainerContent(ctx, container1, x, y, rect1, weight1)
//
drawContainerContent(ctx, container2, x, y, rect2, weight2)
} else {
//
const currentContainer = x < rect2.left ? container1 : container2
const currentRect = x < rect2.left ? rect1 : rect2
drawContainerContent(ctx, currentContainer, x, y, currentRect, 1)
}
}
//
function drawContainerContent(ctx, container, x, y, rect, alpha) {
if (alpha === 0) return
ctx.globalAlpha = alpha
const layers = [
container.querySelector('#bottomCanvas, #bottomCanvas1'),
container.querySelector('#leftCanvas, #rightCanvas'),
container.querySelector('#topCanvas, #topCanvas1')
].filter(canvas => canvas)
layers.forEach(canvas => {
const canvasRect = canvas.getBoundingClientRect()
const canvasX = x - canvasRect.left
const canvasY = y - canvasRect.top
ctx.drawImage(
canvas,
canvasX - 75,
canvasY - 50,
150,
100,
0,
0,
300,
200
)
})
ctx.globalAlpha = 1
}
//
function handleMouseMove(e) {
if (!isZoomed.value) return
const container1 = document.querySelector('#canvas-container')
const container2 = document.querySelector('#canvas-container1')
const rect1 = container1.getBoundingClientRect()
const rect2 = container2.getBoundingClientRect()
//
const isInContainer1 = e.clientX >= rect1.left && e.clientX <= rect1.right &&
e.clientY >= rect1.top && e.clientY <= rect1.bottom
const isInContainer2 = e.clientX >= rect2.left && e.clientX <= rect2.right &&
e.clientY >= rect2.top && e.clientY <= rect2.bottom
if (!isInContainer1 && !isInContainer2) {
isZoomed.value = false
document.removeEventListener('mousemove', handleMouseMove)
return
}
zoomedPosition.x = e.clientX
zoomedPosition.y = e.clientY
// 使
const currentContainer = e.clientX < rect2.left ? container1 : container2
drawMagnifiedArea(e.clientX, e.clientY, currentContainer)
}
//
function handleMouseDown(e) {
if (e.button === 0) {
//
if (isZoomed.value) {
//
isZoomed.value = false
screenshotUrl.value = ''
} else {
//
captureArea(e.clientX, e.clientY)
}
const container = e.target.closest('#canvas-container, #canvas-container1')
if (!container || e.button !== 0) return
const rect = container.getBoundingClientRect()
const isInContainer = e.clientX >= rect.left && e.clientX <= rect.right &&
e.clientY >= rect.top && e.clientY <= rect.bottom
if (!isInContainer) return
if (isZoomed.value) {
isZoomed.value = false
document.removeEventListener('mousemove', handleMouseMove)
} else {
isZoomed.value = true
zoomedPosition.x = e.clientX
zoomedPosition.y = e.clientY
drawMagnifiedArea(e.clientX, e.clientY, container)
document.addEventListener('mousemove', handleMouseMove)
}
}
// function handleKeyPress(e) {
// if (e.key === 'Escape') {
// isShow.value = !isShow.value
// isZoomed.value = false
// screenshotUrl.value = ''
// if (isShow.value) {
// document.addEventListener('mousedown', handleMouseDown)
// } else {
// document.removeEventListener('mousedown', handleMouseDown)
// }
// }
// }
onMounted(() => {
// document.addEventListener('keydown', handleKeyPress)
})
onUnmounted(() => {
//document.removeEventListener('keydown', handleKeyPress)
// document.removeEventListener('mousedown', handleMouseDown)
})
nextTick(() => {
});
const infoParams = defineProps({
Isfd: Boolean
})
// watch props.isFD
watch([() => infoParams.Isfd], ([newfd], [oldds]) => {
if (newfd !== oldds) {
console.log(newfd)
if (newfd) {
document.addEventListener('mousedown', handleMouseDown)
} else {
document.removeEventListener('mousedown', handleMouseDown)
document.removeEventListener('mousemove', handleMouseMove)
isZoomed.value = false
}
}
})
onUnmounted(() => {
document.removeEventListener('mousedown', handleMouseDown)
document.removeEventListener('mousemove', handleMouseMove)
})
</script>
<style scoped>
@ -131,12 +184,14 @@ watch([() => infoParams.Isfd], ([newfd], [oldds]) => {
.magnifier-glass {
position: fixed;
border: 2px solid rgba(255, 0, 0, 0.5);
border-radius: 50%;
transform: translate(-50%, -50%);
background-repeat: no-repeat;
border: 1px solid rgba(255, 0, 0, 0.5);
pointer-events: none;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
transition: all 0.2s ease-out;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
canvas {
transform: scale(1.8);
transform-origin: center center;
}
</style>

View File

@ -126,7 +126,6 @@ function handleMouseDown(event, type) {
const y = event.clientY - rect.top
if (lastPoint.value) {
// 使线
drawLineAndDistance(lastPoint.value, { x, y })
lastPoint.value = null //
} else {
@ -451,7 +450,7 @@ const lead_name = ['I', 'II', 'III', 'aVR', 'aVL', 'aVF']
const rlead_name = ['V1', 'V2', 'V3', 'V4', 'V5', 'V6']
//
//<EFBFBD><EFBFBD><EFBFBD>
function handleFileChange() {
const json = JSON.parse(text.value)