<template>
<div class="wrap">
<div class="origin" :style="{
width: `${initWidth}px`,
height: `${initHeight}px`,
}">
<div class="event-view" @mouseenter="mouseenter" @mousemove="mousemove" @mouseleave="mouseleave"></div>
<img class="img" :src="url">
<div class="mask" v-show="data.show" :style="{
width: `${initWidth / zoom}px`,
height: `${initHeight / zoom}px`,
left: `${data.maskLeft}px`,
top: `${data.maskTop}px`,
}"></div>
</div>
<div class="per-view" v-show="data.show" :style="{
width: `${initWidth}px`,
height: `${initHeight}px`,
}">
<img class="img" :style="{
width: `${initWidth * zoom}px`,
height: `${initHeight * zoom}px`,
left: `${data.perviewLeft}px`,
top: `${data.perviewTop}px`,
}" :src="url" />
</div>
</div>
</template>
<script setup>
import { reactive, defineProps } from 'vue'
const props = defineProps({
zoom: {
type: Number,
default: 2
},
url: {
type: String,
required: true,
default: "https://temp.im/200x200/4CD964/fff"
},
initWidth: {
type: Number,
default: 400
},
initHeight: {
type: Number,
default: 400
},
})
const data = reactive({
show: false,
maskLeft: 0,
maskTop: 0,
perviewLeft: 0,
perviewTop: 0
})
const mouseenter = () => {
data.show = true;
}
const mousemove = (e) => {
const { offsetX, offsetY } = e;
const { initWidth, initHeight, zoom } = props;
const maskWidth = initWidth / zoom;
const maskHeight = initHeight / zoom;
let viewX,viewY;
viewX = offsetX - (maskWidth / 2);
viewY = offsetY - (maskHeight / 2);
// 边界判断
viewX = viewX < 0 ? 0 : viewX;
viewY = viewY < 0 ? 0 : viewY;
if(viewX + maskWidth >= initWidth) {
viewX = initWidth - maskWidth;
}
if(viewY + maskHeight >= initHeight) {
viewY = initHeight - maskHeight;
}
data.maskLeft = viewX
data.maskTop = viewY
data.perviewLeft = -viewX * props.zoom;
data.perviewTop = -viewY * props.zoom;
}
const mouseleave = () => {
data.show = false;
}
</script>
<style lang="scss" scoped>
.wrap {
display: flex;
}
.origin {
position: relative;
.event-view {
position: absolute;
width: 100%;
height: 100%;
z-index: 999;
}
.img {
width: 100%;
height: 100%;
}
.mask {
position: absolute;
background: rgba(255,255,255,.4);
}
}
.per-view {
position: relative;
margin-left: 20px;
overflow: hidden;
.img {
position: absolute;
}
}
</style>
07-22
5927
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)
03-18
545
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)
10-18
439
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)
08-14