实现原理:
当鼠标移入图片区域,显示遮罩层和大图预览区
当鼠标移动,遮罩层要根据鼠标距离屏幕的坐标,动态的改变自己的距离,保证鼠标是在中心点位置
通过计算遮罩层距离屏幕的绝对距离,计算出大图应该距离屏幕的绝对距离
magnify 组件
<template>
<div class="magnify">
<div class="magnify-preview" @mousemove="move($event)" @mouseout="out" ref="magnifyPreview">
<!-- 默认显示图 -->
<img :src="previewImg" alt="">
<!-- 移动遮罩层 -->
<div class="preview-hover" ref="hoverBox"></div>
</div>
<div class="magnify-zoom" v-show="zoomVisiable" ref="magnifyZoom">
<!-- 大预览图 -->
<img :src="zoomImg" alt="" ref="bigImg">
</div>
</div>
</template>
<script>
function offset (el) {
let top = el.offsetTop
let left = el.offsetLeft
while (el.offsetParent) {
el = el.offsetParent
top += el.offsetTop
left += el.offsetLeft
}
return {
left: left,
top: top
}
}
export default {
name: 'magnify',
props: {
previewImg: {
type: String,
default: ''
},
zoomImg: {
type: String,
default: ''
}
},
data () {
return {
zoomVisiable: false,
hoverVisiable: false
}
},
methods: {
out () {
this.zoomVisiable = false
},
move (ev) {
this.init()
// 鼠标距离屏幕的绝对距离
let moveX = ev.clientX
let moveY = ev.clientY
// 大盒子距离屏幕的绝对距离
let offsetLeft = offset(this.magnifyPreview).left
let offsetTop = offset(this.magnifyPreview).top
// left top计算出遮罩层应该距离屏幕的绝对距离
let left = moveX - offsetLeft - this.hoverWidth / 2
let top
if (this.scroll > 0) {
top = moveY - offsetTop + this.scroll - this.hoverHeight / 2
} else {
top = moveY - offsetTop - this.hoverHeight / 2
}
let maxWidth = this.pWidth - this.hoverWidth
let maxHeight = this.pWidth - this.hoverHeight
left = left < 0 ? 0 : left > maxWidth ? maxWidth : left
top = top < 0 ? 0 : top > maxHeight ? maxHeight : top
let percentX = left / (maxWidth)
let percentY = top / (maxHeight)
this.hoverBox.style.left = left + 'px'
this.hoverBox.style.top = top + 'px'
this.bigImg.style.left = percentX * (this.bWidth - this.imgWidth) + 'px'
this.bigImg.style.top = percentY * (this.bHeight - this.imgHeight) + 'px'
this.zoomVisiable = true
},
init () {
this.hoverBox = this.$refs.hoverBox
this.magnifyPreview = this.$refs.magnifyPreview
this.bigImg = this.$refs.bigImg
this.imgBox = this.$refs.magnifyZoom
this.hoverWidth = this.hoverBox.offsetWidth
this.hoverHeight = this.hoverBox.offsetHeight
this.pWidth = this.magnifyPreview.offsetWidth
this.pHeight = this.magnifyPreview.offsetHeight
this.imgWidth = this.bigImg.offsetWidth
this.imgHeight = this.bigImg.offsetHeight
this.bWidth = this.imgBox.offsetWidth
this.bHeight = this.imgBox.offsetHeight
this.scroll = document.documentElement.scrollTop || document.body.scrollTop
}
}
}
</script>
<style lang="scss" scoped>
.magnify {
position: relative;
.magnify-preview {
480px;
height: 480px;
text-align: center;
vertical-align: middle;
border: 1px solid #dededd;
position: relative;
&:hover .preview-hover {
display: block;
visibility: visible;
}
.preview-hover {
box-sizing: border-box;
position: absolute;
display: none;
left: 0;
top: 0;
240px;
height: 240px;
background: url("https://img-tmdetail.alicdn.com/tps/i4/T12pdtXaldXXXXXXXX-2-2.png") repeat 0 0;
cursor: move;
user-select: none;
}
img {
max- 478px;
max-height: 478px;
display: inline-block;
}
}
.magnify-zoom {
480px;
height: 480px;
overflow: hidden;
position: absolute;
left: 485px;
border: 1px solid #dc7a7a;
top: 0;
img {
position: absolute;
top: 0;
left: 0;
}
}
}
</style>
在组件中使用
<template>
<my-magnify :previewImg="magnify.min" :zoomImg="magnify.max"></my-magnify>
</template>
<script>
import MyMagnify from '../components/Magnify.vue'
export default {
data () {
magnify: {
min: '',
max: ''
},
},
components: {
MyMagnify
}
}
</script>