基于vue商品图片轮播和放大镜的方案

实现原理

放大镜的原理用一句话概括,就是根据小图上的鼠标位置去定位大图。

原理图(以2倍放大为例)
基于vue商品图片轮播和放大镜的方案_第1张图片
相信原理图已经画的很明白了, 图中,左侧框是小图框,其蓝色区域为图片遮罩层(需放大区域),右侧框是整个大图目前所在区域,其蓝色区域是放大区域,设置超出隐藏,就实现了放大遮罩区域的效果。
显然,两块蓝色区域存在着某种对应关系,即遮罩的左上角位置(相对于小图,以下称 X 坐标)和放大区域(相对于大图)的左上角位置是成比例的,即放大倍数。计算出 X 坐标后,适当调整背景图的位置,使大图向反方向移动 scale 倍的 X 坐标即可。
X 坐标为(maskX,maskY),以计算 maskX 为例:
鼠标移动中会产生 e.clientX ,标识鼠标与浏览器左侧的距离,小图与浏览器左侧的距离是 left ,由于遮罩始终是一个以鼠标为中心的正方形,所以:
maskX = e.clientX - left - mask/2
同理,
maskY = e.clientY - top - mask/2
大图的对应样式设置为:

{
  left: - maskX * scale + 'px';
  top: - maskY * scale + 'px';
}

效果演示
基于vue商品图片轮播和放大镜的方案_第2张图片
我引用的ui库是elementui,因为我当时需要的是商品可以轮播在加上商品放大效果,如果是简单的商品图片放大大家百度应该方法都差不多,大致都能实现,可是我因为商品需要在x轴上轮播,就必须在css上面加 overflow-x: hidden;我看了几个轮播插件,好像都需要加,因为如果加了 overflow的话,放大的图就不能出现了,后来想了好多办法,找到一种解决办法,代码如下:


    
          

如果大家不需要轮播的话可以直接写下面的代码:

 

css:

.small-box{
    position: relative;

}
.magnifier-zoom{
    position: absolute;
    top: 0;
    left: 0;
}
.magnifier-layer{
    position: absolute;
    top: 0;
    right: 0;
    z-index: 1000;
    overflow: hidden;
    background-color: #fff;
}
.big-box{
    position: absolute;
}
 .magnifier{
     position: relative;
    width: 580px;
      height: 360px;
      border-radius: 8px;
   
  }
   .smallPic{
         width: 580px;
         height: 360px;
         border-radius: 8px;
     }
 computed: {
      bigWidth(){
           return this.configs.scale * this.configs.width;
       },
       bigHeight(){
           return this.configs.scale * this.configs.height;
       }
   },
   mounted () {
       this.$init()
   },
  data(){
      return {
          configs:{
            width:570,//放大区域
            height:360,//放大区域
            maskWidth:210,//遮罩
            maskHeight:210,//遮罩
            maskColor:'rgba(25,122,255,0.5)',//遮罩样式
            maskOpacity:0.6,
            scale:2,//放大比例
          },
          imgObj: {},
          moveLeft: 0,
          moveTop: 0,
          transformMask:`translate(0px, 0px)`,
          showMagnifier:false,
          showMask:false,
      }
    },  
     methods: {
        $init(){
            setTimeout(() => {
                  this.imgObj = this.$el.getElementsByClassName('small-box')[0].getBoundingClientRect();
            }, 500);
        },
        changeshop(e){
            this.showMagnifier = false;
            this.showMask = false;
            this.transformMask = `translate(0px, 0px)`
            this.moveLeft = 0
            this.moveTop = 0
        },
        handMove(e) {
           // 动态获取小图的位置(或者监听 scroll )
            let imgRectNow = this.imgObj;
            let objX = e.clientX - imgRectNow.left;
            let objY = e.clientY - imgRectNow.top;
            
            // 计算初始的遮罩左上角的坐标
            let maskX = objX - this.configs.maskWidth / 2;
            let maskY = objY - this.configs.maskHeight / 2;
            
            // 判断是否超出界限,并纠正
            maskY = maskY < 0 ? 0 : maskY; 
            maskX = maskX < 0 ? 0 : maskX; 
            if(maskY + this.configs.maskHeight >= imgRectNow.height) {
            maskY = imgRectNow.height - this.configs.maskHeight;
            }
            if(maskX + this.configs.maskWidth >= imgRectNow.width) {
            maskX = imgRectNow.width - this.configs.maskWidth;
            }
            
            // 遮罩移动
            this.transformMask = `translate(${maskX}px, ${maskY}px)`;
            
            // 背景图移动
            this.moveLeft = - maskX * this.configs.scale + "px";
            this.moveTop = - maskY * this.configs.scale + "px";
        },
        handOut() {
            this.showMagnifier = false;
            this.showMask = false;
        },
        handOver() {
            this.showMagnifier = true;
            this.showMask = true;
        }
    },

如果不需要轮播图的话就可以不写changeshop这个方法就行,其余的都一样的

采坑结束,如果大家有更好的方法,欢迎在评论里告诉我哦~~~

你可能感兴趣的:(web前端)