原生js实现放大镜

96 阅读2分钟

前言

同事今天问我放大镜怎么弄,我就分享一下我的个人理解,大佬轻喷,了解的可以一起探讨探讨。话不多说,我们来看效果图。 pic1.jpg

html(就不做过多解释了)

<body>
  <div class="box" id="box">
    <div class="small" id="smallBox">
      <img src="images/001.jpg" width="350" alt="" />

      <div class="mask" id="mask"></div>
    </div>
    <div class="big" id="bigBox">
      <img id="bigImg" src="images/0001.jpg" width="800" alt="" />
    </div>
  </div>
</body>

css(就不做过多解释了)

<style>
{
      margin: 0;
      padding: 0;
    }

    .box {
      width: 350px;
      height: 350px;
      margin: 100px;
      border: 1px solid #ccc;
      position: relative;
    }

    .big {
      width: 400px;
      height: 400px;
      position: absolute;
      top: 0;
      left: 360px;
      border: 1px solid #ccc;
      overflow: hidden;
      display: none;
    }

    .mask {
      width: 175px;
      height: 175px;
      background: rgba(255, 255, 0, 0.4);
      position: absolute;
      top: 0;
      left: 0;
      cursor: move;
      display: none;
    }

    .small {
      position: relative;
    }

    .box img {
      vertical-align: top;
    }

    #bigBox>img {
      /*是让里面的图片脱标,为的就是让里面的图片进行一个移动*/
      position: absolute;
    }
 </style>

js

首先我们来一下需求分析

  1. 当你鼠标移入小盒子small:显示大盒子big与遮罩层mask
  2. 鼠标移出小盒子small:隐藏大盒子big与遮罩层mask
  0.获取元素
  let box = document.querySelector('#box')//父盒子
  let smallBox = document.querySelector('#smallBox')//小盒子
  let bigBox = document.querySelector('#bigBox')//大盒子
  let mask = document.querySelector('#mask')//遮罩层
  let bigImg = document.querySelector('#bigImg')//大图片
  1.鼠标移入事件
  smallBox.onmouseenter = function () {
    mask.style.display = 'block'
    bigBox.style.display = 'block'
  }
  2.鼠标移出事件
  smallBox.onmouseleave = function () {
    mask.style.display = 'none'
    bigBox.style.display = 'none'
  }
  1. 鼠标移动小盒子small:
  • a.mask跟随鼠标移动
  • b.鼠标在mask中心
  • c.mask边界检测
  • d.大盒子的图片对应移动
  • 假如mask是50px50px,大盒子是100px100px,鼠标每移动1px,大盒子图片移动2px * 100 / 50 * 1 = 2
    //e.pageX:鼠标触发点到页面左边缘的距离
    //e.pageY:鼠标触发点到页面上边缘的距离
    //box.offsetLeft:父盒子box左边框到页面距离
    //box.offsetTop:父盒子box上边框到页面距离
    //e.pageX - box.offsetLeft:鼠标触发点到smallBox左边框的距离
    //e.e.pageY - box.offsetTop:鼠标触发点到smallBox上边框的距离
 
    let x = e.pageX - box.offsetLeft
    let y = e.pageY - box.offsetTop
    
    //鼠标在mask中心位置:让x和y往左上角偏移mask宽高的一半
    x -= mask.offsetWidth / 2
    y -= mask.offsetHeight / 2
    
    //mask只能在smallBox里面移动
    //0<x<smallBox宽度-mask宽度
    //0<y<smallBox高度-mask高度
    x = x < 0 ? 0 : x
    x = x > smallBox.offsetWidth-mask.offsetWidth ? smallBox.offsetWidth - mask.offsetWidth : x
    y = y < 0 ? 0 : y
    y = y > smallBox.offsetHeight - mask.offsetHeight?smallBox.offsetHeight - mask.offsetHeight : y
    mask.style.left = x + 'px'
    mask.style.top = y + 'px'
    
    //3.2大盒子里面的图片和mask一起移动
    注意点:1.如果mask盒子移动多少,大图片移动 倍数=大盒子宽高/mask宽度
           2.如果mask往右移动,图片就要往左移.mask往下移,图片就要往上移
           
    bigImg.style.left = -x * bigBox.offsetWidth / mask.offsetWidth + 'px'
    bigImg.style.top = -y * bigBox.offsetHeight / mask.offsetHeight + 'px'
  }

总结

其实图片放大镜的实现思路没有那么复杂,主要就是以下两点:

  • 1.遮罩层跟随鼠标移动的原理
  • 2.大盒子跟随遮罩层是相反移动

本文顺着这个思路,做了一个简单的实现,还有一些优化的空间,欢迎各位大佬在评论区讨论。