前言
做电商应用时,难免会遇到商品主图达到放大镜效果的场景。现有的基于Vue的第三方包很少,不能直接重用。今天分享一个基于Vue的高稳定性图像放大镜的方法。
实施原则
放大镜的原理可以用一句话概括,就是根据鼠标在小图片上的位置来定位大图片。
图1示意图(以2倍放大为例)
我相信示意图已经画清楚了。图中左框为小框,其蓝色区域为画面蒙版层(需放大的区域);右框是整个大图当前所在的区域,其蓝色区域是放大区域。如果设置无法隐藏,可以实现放大蒙版面积的效果。
显然,两个蓝色区域之间存在一定的对应关系,即蒙版左上角位置(相对于小图像,以下简称X坐标)与放大区域左上角位置(相对于大图像)成正比,即放大倍数。计算出x坐标后,适当调整背景图像的位置,使大图像反方向移动缩放次数的x坐标。
x坐标为(maskX,maskY),以maskX的计算为例:
当鼠标移动时会生成E.clientX,它标记了鼠标与浏览器左侧的距离。缩略图和浏览器左侧之间的距离是左侧。因为遮罩总是以鼠标为中心的正方形,所以:
maskX=e.clientX - left - mask/2
同样地,
maskY=e.clientY - top - mask/2
大图像的对应样式设置如下:
{ left: - maskX *比例尺' px ';top: - maskY *刻度' px ';}效果演示
图2显示了长图
图3的宽视图显示
图4双放大渲染
图5四倍放大渲染
核心代码
超文本标记语言
一般放大镜实现等宽等高1:1的方形图片,兼容其他比例的图片,设置图片垂直居中对齐,包括小图片和大图片。如果小图不足以填满整个小画框,也可以将左边空白部分放大,但放大后的结果仍然是空白。这样,我们只需要计算背景图像的移动距离,而不需要过多关注图像定位的问题。
模板div class='放大镜'!-Small pick-div class=' Small-box ' @ mouse over='交接' @ mouse move=' hand move ' @ mouse out='交接' img class=' Small pic ' : src=' http 3360 ` $ { src }?x-oss-process=image/resize,l _ 836 ` '/div class=' magnifier-zoom ' v-show=' show mask ' : style=' { background : configs . maskcolor,height : configs . maskwidth ' px ',width : configs . mask hx8 ' px ',opa city 3360 configs . maskopacity,transform 3360 transform mask } '/div/div!-大图,注意错误-div class='放大镜-图层' v-show='显示放大镜' : style=' {width : configs。宽度' px ',高度:配置。高度' px ',左侧: configs . width 20 ' px ' } ' div class=' big-box ' : style=' { width : bigWidth 'px ',高度: big width ' px ',左侧: moveLeft,top : move top } ' div class=' big-box-img ' : style=' { width : big width-2 ' px ',高度3: big
主要有三个事件函数。
切换:鼠标在小框上进入事件时,会显示蒙版和放大区域,并计算小框的位置信息。
HandOver() {//计算小框架在浏览器中的位置这。imgobj=这个。$ el。getElementByclassName('小方框')[0];this . imgrectnow=this . imgobj . getboundingclientrect();this.showMagnifier=truethis.showMask=true}handMove:鼠标在小图片上的移动事件,发生在after、计算数据、移动蒙版和背景图片之后;
handMove(e) { //计算初始的遮罩左上角的坐标让objX=e . client x-这个。imgrectnow。向左;让objY=e . clienty-这个。imgrectnow。顶部;//计算初始的遮罩左上角的坐标让maskX=Objx-这个。配置。maskwidth/2;让MaSky=Objy-这个。配置。mask h AiR/2;//判断是否超出界限,并纠正maskY=maskY 0?0 : maskYmaskX=maskX 0?0 : maskXif(MaSky这个。配置。MaSKhA8=这个。IMGRECtNow。高度){ MaSky=这个。IMGRECtNow。身高-这个。配置。MaSKhA8} if(maskX这个。配置。maskwidth=这个。imgrectnow。宽度){ maskX=这个。imgrectnow。宽度-这个。配置。maskwidth} //遮罩移动这个。transform mask=` translate($ { MaSkx } px,$ { MaSky } px)`;//背景图移动这个。moveleft=-maskX *这个。配置。刻度“px”;这个。移动top=-MaSky *这个。配置。刻度“px”;}讲义:鼠标离开小图事件,此时无放大镜效果,隐藏遮罩和放大区域。
讲义(){ this . show magnifier=false this . show mask=false }以上三个事件基本上就实现了图片的放大镜功能。
但仔细看,你会发现每次移入小图框都会触发一次移交事件,并且计算一次小图框DOM (imgObj)。
为了优化此问题,可以用初始化标识是否是页面加载后首次触发移交事件,如果是初始化就计算imgObj信息,否则不计算。
切换(){ if(!这个。init){这个。init=true//原移交事件.} this . show magnifier=true this . show mask=true },在测试的过程中,发现页面滚动后,会出现遮罩定位错误的情况,原来是因为初始化时,我们固定死了小图框的位置信息(存放在this.imgRectNow),导致手动移动事件中的移动数据计算错误。
解决这个问题有两种方案:
监听卷起事件,更新this.imgRectNow在手动移动事件中更新this.imgRectNow。这里选择了第二种。
handMove(e) { //动态获取小图的位置(或者监听滚动)让imgRectNow=这个。imgobj。getboundingclientrect();让objX=e . clientx-imgrectnow。向左;让objY=e . clienty-imgrectnow。顶部;//原手动移动事件剩余内容.},综合以上,我们已经实现了一个完美的图片放大镜功能。最终的射流研究…如下所示:
data(){ return { imgobj : },moveLeft: 0,moveTop: 0,transform mask : ` translate(0px,0px)`,show放大镜:false,showMask:false,init: false,};},计算出: { BigWidth(){返回这个。配置。缩放*这个。配置。宽度;},BigHout(){ 0返回这个。配置。缩放*这个。配置。身高;}},methods: { handMove(e) { //动态获取小图的位置(或者监听滚动)让imgRectNow=这个。imgobj。getboundingclientrect();让objX=e . clientx-imgrectnow。向左;让objY=e . clienty-imgrectnow。顶部;//计算初始的遮罩左上角的坐标让maskX=Objx-这个。配置。maskwidth/2;让MaSky=Objy-这个。配置。mask h AiR/2;//判断是否超出界限,并纠正maskY=maskY 0?0 : maskYmaskX=maskX 0?0 : maskXif(MaSky这个。配置。mask h8=imgrectnow。高度){ MaSky=imgrectnow。身高-这个。配置。口罩h8;} if(maskX这个。配置。maskwidth=imgrectnow。width){ maskX=imgrectnow。宽度-这个。配置。maskwidth} //遮罩移动这个。transform mask=` translate($ { MaSkx } px,$ { MaSky } px)`;//背景图移动这个。moveleft=-maskX *这个。配置。刻度“px”;这个。移动top=-MaSky *这个。配置。刻度“px”;},讲义(){ this . show magnifier=false this . show mask=false },RoBErt(){ if(!这个。init){这个。init=truethis.imgObj=this .$el.getElementsByClassName('小方框')[0];} this . show放大镜=truethis.showMask=true}}使用方法
本示例中的固定参数:小图框:420 * 420 。
程序可接受参数:
//小图片地址src: {type: String,},//大图片地址BigSRC: {Type: String,},//配置项配置: {type: Object,Default () {return {width:420,//放大区域height:420,//放大区域maskWidth:210,///屏蔽maskh x8 3360210,//屏蔽maskColor}}图2为长图,小图最大边缘不超过836px(双图),大图分辨率尽可能高以达到视觉效果,程序会根据配置项自动设置相应的高度和宽度。长图和宽图效果对比见图3。
配置项可以根据应用场景进行设置。本例中的配置项为2倍放大,效果如图4所示,4倍放大的效果如图5所示。
摘要
其实图片放大镜的实现并没有那么复杂,有两个核心点:
大小图像的定位,蒙版和放大区域的创建了解放大镜的原理,用代码实现DOM的移动。按照这个思路,本文做了一个简单的实现,还有一定的优化空间。欢迎大家在评论区讨论。虽然代码看起来不太优雅,但足够清晰,感兴趣的学生可以自己尝试。
以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。