用JS逐步分解实现放大镜(看完就有收获)

案例描述

在浏览器的左边有一张大图,下面有两张小图,点击任何一张小图会在大图的位置显示这张小图的画面。进入大图,鼠标所指之处有一个透明的黄色区域,而在大图的右边(以下称超大图)会放大这一区域

案例图示

在这里插入图片描述

HTML

<body>
    <div id="box">
        <div id="small">
            <img src="./program1/images/1.jpg" >
            <span id="mask"></span>
        </div>
        <div id="big">
            <img src="./program1/images/1.jpg" >
        </div>
    </div>
    <div id="list">
        <ul>
            <li><img src="./program1/images/1.jpg" width="100px"></li>
            <li><img src="./program1/images/2.jpg" width="100px"></li>
        </ul>
    </div>
</body>

CSS样式

详解请看注释

<style>
    * {
        padding: 0;
        margin: 0;
        box-sizing: border-box;
        list-style: none;
        border: none;
    }
    #box {
        width: 250px;
        height: 160px;
        margin-left: 100px;
        margin-top: 100px;
        position: relative;
    }
    #small {
        width: 100%;
        height: 100%;
        border: 1px solid #ccc; 
        /* 放大镜操作 */
        position: relative;       
    }
    #small img{
        width: 100%;
        height: 100%;
        padding: 2px;

    }
    /* 显微镜 */
    #mask {
        width: 50px;
        height: 50px;
        /* 透明图 */
        background-color:rgba(255, 255, 0,.4);
        position: absolute;
        left: 0;
        top: 0;
        cursor: move;
        /* 隐藏 */
        display: none;
    }
    #big {
        width: 400px;
        height: 255px;
        border: 1px solid #ccc;
        /* 为以后大图位置改变作准备 */
        position: absolute;
        /* 250 + 10 margin */
        left: 260px;     
        top: 0;
        /* 图片超出部分隐藏 */
        overflow: hidden;
        /* 整个大图开始是隐藏的 */
        display: none;
    }
    #big img {
        width: 700px;
        padding: 2px;
        position: absolute;
        left: 0;
        top: 0;
        margin: 0 auto;
        background-color: red;
    }
    #list {
        margin-top: 5px;
        margin-left: 100px;
    }
    #list li {
        float: left;
        margin-right: 5px;
        cursor: pointer;
    }
</style>

JS代码

JS分解代码----小图点击事件

(1)首先设置一个value属性用于改变small_img中的图片src,value的值为其下标+1
(2)监听li中的点击事件时,要改变small_img(大图)中的图片展示和big_img(超大图)中的图片展示

 for (let i = 0; i < allLi.length; i++) {
            var li = allLi[i];
            //设置一个value属性用于改变small_img中的图片src
            li.setAttribute('value',i+1);
            //监听li中的点击事件
            li.addEventListener('click',function(){
                //改变small_img中的图片展示
                small_img.setAttribute('src',"./program1/images/" + this.getAttribute('value') +".jpg");
                //改变big_img中的图片展示
                big_img.setAttribute('src',"./program1/images/" + this.getAttribute('value') +".jpg");
            });
        }

JS分解代码----鼠标进入和移出

鼠标进入和移出都要改变放大镜和超大图的display属性。
进入时display属性值为*“block”*
移出时display属性值为*“none”*

//监听鼠标进入box
        box.addEventListener('mouseover',function() { 
            //放大镜显示
            mask.style.display = 'block';
            //big图片显示
            big.style.display = 'block';       
        });

        //监听鼠标移出box
        box.addEventListener('mouseout',function(){
            //放大镜隐藏
            mask.style.display = 'none';
            //big图片隐藏
            big.style.display = 'none';
        })
    });

JS分解代码----鼠标的移动

在鼠标进入事件中监听鼠标的移动
这里运用到事件对象和offset家族的知识
可以参考:
事件对象
offset家族
注意事项看注释

 //监听鼠标的移动
small.addEventListener('mousemove',function(event){
//事件对象
var e = event || window.event;
//获取鼠标的位置  鼠标显示在mask中间:减去自身宽高度的一半
//最好用pageX、pageY,不要用clientX、clientY 防止有分页时出错
 var small_x = event.pageX - box.offsetLeft - mask.offsetWidth*0.5;
var small_y= event.pageY - box.offsetTop - mask.offsetHeight*0.5;

JS分解代码----碰撞事件,放大镜的移动

写完上述代码,你会发现放大镜也能去到大图以外的区域,这不是我们所期望的,这里就需要用到碰撞事件了
这里还是用到了offset家族的知识
这里用到的思维是用if判断条件限制上下左右的边界
放大镜的移动就是改变它的top和left值(因为它相对父元素绝对定位)
不理解offset,请参考:offset家族
注意事项看注释


//放大镜碰撞    

//相对于box  因为box有定位
if(small_x <= 0)
	small_x = 0;
else if( small_x >= box.offsetWidth-mask.offsetWidth)
	small_x = box.offsetWidth-mask.offsetWidth - 2;   //除去边框
if(small_y <= 0)
	small_y = 0;
else if( small_y >= box.offsetHeight-mask.offsetHeight)
	small_y = box.offsetHeight-mask.offsetHeight - 2;

//放大镜跟着鼠标的位置 
mask.style.left = small_x + 'px';
mask.style.top = small_y + 'px';
               

JS分解代码----超大图的位置改变

big_img.style.leftbig_img.style.top为负值(你可以试试去掉负号是什么样的效果)
这里的重点是这个公式

 //big_img中的位置相应改变
//公式:small_x/big_x = small_width/big_img_width
               
big_img.style.left = - (event.pageX - box.offsetLeft) /(small.offsetWidth / big.offsetWidth) + 'px';
big_img.style.top = -( event.pageY - box.offsetTop)/( small.offsetHeight / big.offsetHeight) + 'px';

JS全部代码展示

<script>
    window.addEventListener ('load',function(){
        //获取元素
        var small = $('small');
        var big = $('big');   
        var mask = $('mask');
        var allLi = document.getElementsByTagName('li');
        var small_img = small.children[0];
        var big_img = big.children[0];

        //遍历每一个li中的点击事件
        for (let i = 0; i < allLi.length; i++) {
            var li = allLi[i];
            //设置一个value属性用于改变small_img中的图片src
            li.setAttribute('value',i+1);
            //监听li中的点击事件
            li.addEventListener('click',function(){
                //改变small_img中的图片展示
                small_img.setAttribute('src',"./program1/images/" + this.getAttribute('value') +".jpg");
                //改变big_img中的图片展示
                big_img.setAttribute('src',"./program1/images/" + this.getAttribute('value') +".jpg");
            });
        }

        //监听鼠标进入box
        box.addEventListener('mouseover',function() { 
            //放大镜显示
            mask.style.display = 'block';
            //big图片显示
            big.style.display = 'block';

            //监听鼠标的移动
            small.addEventListener('mousemove',function(event){
                //事件对象
                var e = event || window.event;
                //获取鼠标的位置  鼠标显示在mask中间:减去自身宽高度的一半
                //最好用pageX、pageY,不要用clientX、clientY 防止有分页时出错
                var small_x = event.pageX - box.offsetLeft - mask.offsetWidth*0.5;
                var small_y= event.pageY - box.offsetTop - mask.offsetHeight*0.5;


                //放大镜碰撞    
                // console.log(mask.offsetLeft) ;
                //相对于box  因为boxx有定位
                if(small_x <= 0)
                    small_x = 0;
                else if( small_x >= box.offsetWidth-mask.offsetWidth)
                    small_x = box.offsetWidth-mask.offsetWidth - 2;   //除去边框
                if(small_y <= 0)
                    small_y = 0;
                else if( small_y >= box.offsetHeight-mask.offsetHeight)
                    small_y = box.offsetHeight-mask.offsetHeight - 2;

                 //放大镜跟着鼠标的位置 
                mask.style.left = small_x + 'px';
                mask.style.top = small_y + 'px';
               
               //big_img中的位置相应改变
               //公式:small_x/big_x = small_width/big_img_width
               
                big_img.style.left = - (event.pageX - box.offsetLeft) /(small.offsetWidth / big.offsetWidth) + 'px';
                big_img.style.top = -( event.pageY - box.offsetTop)/( small.offsetHeight / big.offsetHeight) + 'px';


            });
           
        });

        //监听鼠标移出box
        box.addEventListener('mouseout',function(){
            //放大镜隐藏
            mask.style.display = 'none';
            //big图片隐藏
            big.style.display = 'none';
        })
    });

    //封装
    function $(id) {
        return typeof id === 'string'? document.getElementById(id):null;
    }
</script>
发布了51 篇原创文章 · 获赞 26 · 访问量 1827

猜你喜欢

转载自blog.csdn.net/qq_45473786/article/details/105012509
今日推荐