• 【京东详情页】——原生js爬坑之放大镜


    一、引言

    在商城的详情页中,放大镜的功能是很常见的。这里京东详情页就要做一个仿放大镜的效果,预览如下:

     

    二、实现原理

    实际上,放大镜的实现是单纯用几个div,鼠标移入其中一个小图div,触发事件显示另一个div中的大图。

    并非真的使用了某种flash或插件之类,用到放大的效果。所以,网页中的放大镜功能都是模拟。

    1、移动功能

     小坑:ul有left ,左边距不为0,有20px的间距,所以,应到的位置要加20px作为抵消。

    const  LiWIDTH=62;//li的宽
    const  OFFSET=20;//ul的起始left

    注意:在程序中,尽量不要把数值写死,万一后面再改需求的时候,要改变数值,就不方便了。

    • 当li总个数 - moved左移的li个数 =  5时,后面的backward按钮禁用

    • 当moved左移的个数 = 0时,前面的forward按钮禁用
        var LICOUNT = document.querySelectorAll(
            "#icon_List>li"
        ).length;//所有li的个数
        var moved = 0;//左移的li个数
        var aForward=document.querySelector("a.forward");
        var aBackward=document.querySelector("a.backward");
        aForward.addEventListener("click", li_move);
        aBackward.addEventListener("click", li_move);
        function li_move(){
            //this->a
            //如果当前a的class中没有disabled
            if(this.className.lastIndexOf("disabled")==-1){
            if(this.className=="forward"){
                moved++;
            }else{
                moved--;
            }
            //设置ul的left为-LIWIDTH*moved+OFFSET
            this.parentNode.lastElementChild.style
                .left=-LIWIDTH*moved+OFFSET+"px";
            checkA()
            }
        }
        //检查两个a的状态
        function checkA(){
              if(moved==0){
                  aBackward.className+=" disabled"//因为是加className 所以disable前要有空格
              }else if(LICOUNT-moved==5){
                  aForward.className+=" disabled"
              }else{
                  aBackward.className="backward";
                  aForward.className="forward";
              }
        }

    以上:实现小图预览列表的“移动”功能。

    2、大图变换

    小坑:和小图对应一样的大图显示

    规律:大图和小图的图片命名基本一样,唯一不同的地方——大图多加一个“-m”。

    解决方法:获得小图的img的src,在后面加“-m”,把新路径设置给大图的mImg的src中。

    小坑:小图预览列表有8个,如果每一个都要加“鼠标移入/移出”事件,太繁琐。

    解决方法:把事件“鼠标移入/移出”绑定给整个ul,但触发的区域,要设置为img,只有目标元素是img时,才能执行事件。

    var mImg=document.getElementById("mImg");
     //为id为icon_list的ul绑定鼠标进入事件:    document.getElementById("icon_list").addEventListener("mouseover",
           function(e){
               if(e.target.nodeName=="IMG"){
                   var src= e.target.src;//获得当前小图片src
                   var i=src.lastIndexOf(".");//获得最后一个.的位置
                   src=src.slice(0,i)+"-m"+src.slice(i);  //在最后一个.前拼-m
                   mImg.src=src;//设置mImg的src为src
               }
           }
        )

    3、透明遮罩

    小坑:mask为小的半透明遮罩,superMask是为了分担img元素事件处理负担的一个辅助div。

    原因:因为img的负担很重,它要把图片下载下来,要一点一点的画出来,已经很有负担。之后,在触发事件mousemove时,还要用到它,而且极其的频繁。哪怕移动到一个很小的地方,也会触发这个mousemove事件,这么频繁的触发,这个事件处理它处理不了。结果,就是会导致很卡,img元素反应不过来。

    解决方法:在img上面套一个和img一样大的div。这样做的好处是,看着也是在图片上移动,但superMask帮img分担了事件处理这份工作。所以之后的所有事件都要绑定在superMask身上,而不要绑定在img身上。(事件:鼠标移入/移出/移动)

    大坑:遮罩如果不限制移动范围,会超出指定大图显示区域。

    解决方法:top,left在计算完成之后,不能马上设置,还要做一点加工。设置移动的最大范围值MAX,当top或left计算值小于0时,设为0,大于MAX时,设为MAX。

    const MSIZE=175;//mask的大小
    const SMSIZE=350;//superMask的大小
       //获得id为superMask的div
       var sm=document.getElementById("superMask");
        var mask=document.getElementById("mask");
        sm.addEventListener("mouseover",
            function(){
                mask.style.display="block";
            }
        );
        sm.addEventListener("mouseout",
            function(){
                mask.style.display="";
            }
        );
        var MAX=SMSIZE-MSIZE;
       //为sm绑定鼠标移动事件
        sm.addEventListener("mousemove",
            function(e){
                var x= e.offsetX,
                    y= e.offsetY;
                var top=y-MSIZE/ 2,
                    left=x-MSIZE/2;
                if(top<0) top=0;
                else if(top>MAX) top=MAX;
                if(left<0) left=0;
                else if(left>MAX) left=MAX;
                mask.style.cssText="display:block; left:"+left+"px; top:"+top+"px";
            }
        )

    4、放大镜

    div显示图片的原理:背景图片,设置src,和前面一样,获得mImg的src,把后面的“-m”改为“-l”,新路径设置成div的背景图片。

    var lgDiv=document.getElementById("largeDiv");
        sm.addEventListener("mouseover",
            function(){
                mask.style.display="block";
                lgDiv.style.display="block";
                var src=mImg.src;
                var i=src.lastIndexOf(".");
                src=src.slice(0,i-1)+"l"+src.slice(i);
                lgDiv.style.backgroundImage="url("+src+")";
            }
        );
        sm.addEventListener("mouseout",
            function(){
                mask.style.display="";
                lgDiv.style.display="";
            }
        );
        var MAX=SMSIZE-MSIZE;
        sm.addEventListener("mousemove",
            function(e){
                var x= e.offsetX,
                    y= e.offsetY;
                var top=y-MSIZE/ 2,
                    left=x-MSIZE/2;
                if(top<0) top=0;
                else if(top>MAX) top=MAX;
                if(left<0) left=0;
                else if(left>MAX) left=MAX;
                mask.style.cssText="display:block; left:"+left+"px; top:"+top+"px";
                lgDiv.style.backgroundPosition=-left*2+"px "+ -top*2+"px";
            }
        )

     注:转载请注明出处

  • 相关阅读:
    Android studio 快捷键记录
    Android开发 判断目标Fragment是否在前台
    Android开发 build.gradle的使用记录
    Android开发 在Application用于初始化的工具类
    Android开发 因为模块化导致findViewById返回为空null
    Android开发 本地广播
    Android开发 报错: xxx does not have a NavController set on xxx
    Android开发 GridLayout网格布局
    Android开发 Fragment启动Activity在使用onActivityResult的一些问题
    Html 创建自定义标签并且被jQuery获取到
  • 原文地址:https://www.cnblogs.com/ljq66/p/7577374.html
Copyright © 2020-2023  润新知