最近看到放大镜相关的帖子,所以也想自己实现下。 查看原帖
解析
- 外层定位为相对定位,放大镜和遮罩为绝对定位,鼠标移入遮罩层放大镜显示移出则不显示
- 可以根据需要设置外层宽高,原图和外层同宽高,只需传入图片源就行
- 通过配置
scale自动设置放大镜中图片宽高(原图*scale)
实际项目中应用
源码
<template>
<div class="image-magnifier">
<!-- 原图片 -->
<el-image ref="origin" class="img-src-org" :src="src" :fit="fit" />
<!-- 放大镜 -->
<div v-show="isShow" class="magnifier" :style="magnifierWrapStyle">
<el-image
class="img-src-magnifier"
:src="src"
:style="magnifierImgStyle"
:fit="fit"
/>
</div>
<!-- 遮罩 -->
<div
class="mask"
@mouseenter="handleEnter"
@mouseleave="handleLeave"
@mousemove="moveDebounce"
/>
</div>
</template>
<script>
function debounce(fn, delay) {
let timer
return function() {
const context = this
const args = arguments
clearTimeout(timer)
timer = setTimeout(function() {
fn.apply(context, args)
}, delay)
}
}
// 图片放大镜
export default {
name: 'ImageMagnifier',
props: {
// 图片源
src: {
type: String,
default: ''
},
// 放大镜尺寸
magnifierSize: {
type: [String, Number],
default: 160
},
// 放大倍数
scale: {
type: [String, Number],
default: 1.8
},
// 确定图片如何适应容器框,同原生 object-fit
fit: {
type: String,
default: ''
}
},
data() {
return {
isShow: false,
magnifierLeft: 0,
magnifierTop: 0,
magnifierImgLeft: 0,
magnifierImgTop: 0,
moveDebounce: () => {},
orgW: this.magnifierSize,
orgH: this.magnifierSize
}
},
computed: {
magnifierWrapStyle() {
const { magnifierSize, magnifierLeft, magnifierTop } = this
return {
width: magnifierSize + 'px',
height: magnifierSize + 'px',
left: magnifierLeft - magnifierSize / 2 + 'px',
top: magnifierTop - magnifierSize / 2 + 'px'
}
},
magnifierImgStyle() {
const { orgW, orgH, magnifierImgLeft, magnifierImgTop, scale } = this
return {
width: orgW * scale + 'px',
height: orgH * scale + 'px',
left: magnifierImgLeft + 'px',
top: magnifierImgTop + 'px'
}
}
},
mounted() {
// 防抖
this.moveDebounce = debounce(this.handleMove, 3)
const $org = this.$refs.origin
// 原图宽
this.orgW = $org.$el.clientWidth
// 原图高
this.orgH = $org.$el.clientHeight
},
methods: {
handleMove(e) {
const { offsetX, offsetY } = e
const { orgW, orgH, scale, magnifierSize } = this
// 放大镜定位
this.magnifierLeft = offsetX
this.magnifierTop = offsetY
// 鼠标在遮罩层中所处位置相对遮罩层宽/高的比例(遮罩层和外层及原图宽高一致)
const percW = offsetX / orgW
const percH = offsetY / orgH
// 放大镜中图片定位
this.magnifierImgLeft = -percW * orgW * scale + magnifierSize / 2
this.magnifierImgTop = -percH * orgH * scale + magnifierSize / 2
},
handleEnter() {
this.isShow = true
},
handleLeave() {
this.isShow = false
}
}
}
</script>
<style lang="scss" scoped>
.image-magnifier {
position: relative;
}
.img-src-org {
width: 100%;
height: 100%;
}
.img-src-magnifier {
position: absolute;
}
.magnifier {
position: absolute;
overflow: hidden;
border-radius: 50%;
box-shadow: 0 0 20px 4px #000;
left: 0;
top: 0;
background-color: #fff;
z-index: 2;
}
.mask {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
z-index: 3;
}
</style>