vue实现图片局部放大镜交互功能
一、前言
今天看到两个挺有意思的css交互效果————放大镜。
下面就带jym来看看,这两种效果要如何实现吧。
二、放大镜
1、整体思路
①通过注册鼠标的移入、移出、移动事件,实现放大镜的效果
移入之后就会有一个固定大小的遮罩层,这个部分就是要放大的区域,记录下相关的数据信息,如left、top等,为后续的放大效果,积累原始数据。
②对鼠标移动边界做限定处理
这里会涉及一个边界问题,由于遮罩层为一个固定大小的区域,且以鼠标为中心,所以当鼠标靠近边界的时候,应该考虑边界情况下,鼠标和遮罩层移动的特殊情况。
③通过原始数据计算出放大图片的偏移数据。
得到原始数据后,根据放大的倍数,计算出放大图片的偏移值,通过响应式控制放大图片的显示。
2、具体实现
① html部分
结构比较简单,box为原图片,绑定两个鼠标事件,用来控制各种参数; 几个都元素分别都赋值ref,便于后续js的动态计算。
<div class="box" ref="choose" @mousemove="mousemove" @mouseout="mouseout">
<div v-show="showimgage" class="mask" ref="mask"></div>
<img src="../../../assets/images/alarm/55216891.jpg" alt="">
</div>
<div v-show="showimgage" class="box1" ref="lagrebox">
<img src="../../../assets/images/alarm/55216891.jpg" ref="large" alt="">
</div>
② css部分
基本上定格好宽高比,同时放大镜的精髓是position: absolute;通过控制元素的left、top来实现效果的,别忘记了溢出部分要隐藏。
这里box1是放大后的,图片的宽高一共放大了6倍。
.box {
width: 300px;
height: 300px;
position: absolute;
left: 50px;
img {
width: 100%;
height: 100%;
}
.mask {
width: 100px;
height: 100px;
background: rgba(0,255,0,0.2);
position: absolute;
left: 0;
top: 0;
}
}
.box1 {
width: 600px;
height: 600px;
position: absolute;
left: 550px;
overflow: hidden;
img {
width: 300%;
height: 300%;
position: absolute;
left: 0;
top: 0;
}
}
③ js部分
定义一个变量用来控制遮罩层和放大后图片的显示
showimgage: false
主要分三个函数,getPosition函数主要来获取元素的初始偏移值,用于计算的初始化。 mousemove函数是计算当前鼠标位置下,遮罩层mask和放大后图片的显示位置。 moveout函数则是隐藏显示。
// 获取元素到文档区域的坐标
getPosition: function(element){
var dc = document,
rec = element.getBoundingClientRect(),
x = rec.left, // 获取元素相对浏览器视窗window的左、上坐标
y = rec.top;
x += dc.documentElement.scrollLeft || dc.body.scrollLeft;
y += dc.documentElement.scrollTop || dc.body.scrollTop;
return {
left: x,
top: y
};
},
这里细说下mousemove的撰写思路。
1、开启隐藏的遮罩层和放大后的图片;
2、获取遮罩层left和top偏移值,
left = 鼠标所在位置的x - 元素本身的偏移值x - 遮罩层的一半宽度
top = 鼠标所在位置的y - 元素本身的偏移值y - 遮罩层的一半高度
还有就是maxX和maxY,这里是判断遮罩层的方块,是否超出了图片,也就是极限情况, 超出的话要限制在图片内,直到鼠标彻底移出图片,触发隐藏。
赋值给到遮罩层后,根据遮罩层的宽与放大后图片的宽度,计算出scale的倍数,将left和top乘以负数倍的scale之后得到的值,赋值给到放大后的图片,就实现了放大镜的交互效果了。
mousemove(event) {
this.showimgage = true
let pos = this.getPosition(this.$refs.choose)
// 获取图片
let choose = this.$refs.choose
let mask = this.$refs.mask
let lagre = this.$refs.large
let lagrebox = this.$refs.lagrebox
let left = event.pageX - pos.left - mask.offsetWidth / 2
let top = event.pageY - pos.top - mask.offsetHeight / 2
// 约束范围
if(left <= 0) {
left = 0
}
let maxX = choose.getBoundingClientRect().width - mask.getBoundingClientRect().width
if(left >= maxX) {
left = maxX
}
if(top <= 0) {
top = 0
}
let maxY = choose.getBoundingClientRect().height - mask.getBoundingClientRect().height
if(top >= maxY) {
top = maxY
}
mask.style.left = left + 'px'
mask.style.top = top + 'px'
let scale = lagrebox.getBoundingClientRect().width / mask.getBoundingClientRect().width * -1
lagre.style.left = scale * left + 'px'
lagre.style.top = scale * top + 'px'
},
mouseout(event) {
this.showimgage = false
}
效果
插曲
如果你正在使用vue3,那还可以试试vue3官方推荐的工具库vueuse/core,里面有现成的useMouseInElement可以轻松实现放大镜效果。
import { useMouseInElement } from '@vueuse/core'
有兴趣的小伙伴可以去查下相关资料。
三、小结
实现思路还是比较简单易懂的,朋友们可以试试看。
ps: 我是地霊殿__三無,希望能帮到你。
转载自:https://juejin.cn/post/7249204284168093752