ECG/src/views/ECG/ECGSB.vue
2025-01-03 15:30:59 +08:00

293 lines
8.6 KiB
Vue

<template>
<div class="magnifier" v-show="isShow">
<div
v-if="isZoomed"
class="magnifier-glass"
:style="{
left: zoomedPosition.x + 'px',
top: zoomedPosition.y + 'px',
transform: `translate(-50%, -50%) scale(1)`,
width: '300px',
height: '200px',
backgroundColor: 'white'
}"
>
<canvas ref="magnifierCanvas" width="300" height="200"></canvas>
</div>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
const isShow = ref(true)
const isZoomed = ref(false)
const magnifierCanvas = ref(null)
const zoomLevel = 1.8
const zoomedPosition = reactive({
x: 0,
y: 0
})
// 绘制放大区域
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 (false) {
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)
}
} else {
drawContainerContent(ctx, container1, x, y, rect1, 1)
drawContainerContent(ctx, container2, x, y, rect2, 1)
}
}
// 新增:绘制单个容器内容的辅助函数
function drawContainerContent_old(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 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
const canvasY_max = y + 50 >= rect.bottom ? rect.bottom : y + 50
if (['topCanvas', 'topCanvas1'].includes(canvas.id)) {
const leftCanvas = container.querySelector('#leftCanvas, #rightCanvas')
if (canvasRect.right > leftCanvas.getBoundingClientRect().right) {
let borderLeft =
x - leftCanvas.getBoundingClientRect().right > 75
? x - 75
: leftCanvas.getBoundingClientRect().right
let borderLeft_span =
x <= leftCanvas.getBoundingClientRect().right
? 75 + leftCanvas.getBoundingClientRect().right - x
: x - leftCanvas.getBoundingClientRect().right >= 75
? 0
: 75 - x + leftCanvas.getBoundingClientRect().right
let canvasRectRight_effective =
rect.right > canvasRect.right ? canvasRect.right : rect.right
if (
borderLeft_span < 150 &&
borderLeft >= leftCanvas.getBoundingClientRect().right &&
borderLeft <= canvasRectRight_effective
) {
let borderRight =
borderLeft_span > 75
? leftCanvas.getBoundingClientRect().right + 150 - borderLeft_span
: x + 75
if (borderRight >= canvasRectRight_effective) borderRight = canvasRectRight_effective
let swidth = borderRight - borderLeft
ctx.drawImage(
canvas,
borderLeft - canvasRect.left,
canvasY - 50,
swidth,
canvasY_max - (y - 50),
borderLeft_span * 2,
0,
swidth * 2,
(canvasY_max - (y - 50)) * 2
)
}
}
} else if (['bottomCanvas', 'bottomCanvas1'].includes(canvas.id)) {
const leftCanvas = container.querySelector('#leftCanvas, #rightCanvas')
let canvasRectRight_effective = rect.right > canvasRect.right ? canvasRect.right : rect.right
if (x + 75 > leftCanvas.getBoundingClientRect().right && x - 75 < canvasRectRight_effective) {
let swidth = x + 75 <= canvasRectRight_effective ? 150 : 75 + canvasRectRight_effective - x
ctx.drawImage(
canvas,
canvasX - 75,
canvasY - 50,
swidth,
canvasY_max - (y - 50),
0,
0,
swidth * 2,
(canvasY_max - (y - 50)) * 2
)
}
} else {
ctx.drawImage(
canvas,
canvasX - 75,
canvasY - 50,
150,
canvasY_max - (y - 50),
0,
0,
300,
(canvasY_max - (y - 50)) * 2
)
}
})
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) {
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
nextTick(() => {
zoomedPosition.x = e.clientX
zoomedPosition.y = e.clientY
drawMagnifiedArea(e.clientX, e.clientY, container)
document.addEventListener('mousemove', handleMouseMove)
})
}
}
const infoParams = defineProps({
Isfd: Boolean
})
watch([() => infoParams.Isfd], ([newfd], [oldds]) => {
if (newfd !== oldds) {
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>
.magnifier {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 9999;
}
.magnifier-glass {
position: fixed;
border: 1px solid rgba(255, 0, 0, 0.5);
pointer-events: none;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
canvas {
transform: scale(1.8);
transform-origin: center center;
}
</style>