原生js实现放大镜效果

记录一次原生js实现放大镜效果。

效果图

在这里插入图片描述

设计思路

基本架子

先弄一个容器放正常的图片,中间那个蒙版(稍微有点透明的白色正方形),肯定给绝对定位,动态调lefttop值,

所以子绝父相,父容器给相对定位。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .zoom-info {
      width: 400px;
      height: 400px;
      border: 1px solid pink;
    }

    .zoom-info .zoom img {
      width: 100%;
      height: 100%;
      position: relative;
    }
  </style>
</head>

<body>
  <div class="zoom-info">
    <img src="./2.png" alt="">
  </div>
</body>

</html>

视图:

在这里插入图片描述

蒙版

在弄个正方形蒙版出来,这个正方形蒙版,就是说,你鼠标移动到这个图片里面时,正方形的蒙版的中心肯定是跟随你的鼠标移动的。就是你想放大的那个区域。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .zoom-info {
      width: 400px;
      height: 400px;
      border: 1px solid pink;
    }

    .zoom-info img {
      width: 100%;
      height: 100%;
      position: relative;
    }

    /* 新增 */
    .zoom-info .mask {
      width: 200px;
      height: 200px;
      background: rgba(255, 255, 255, 0.5);
      position: absolute;
      border: 1px solid #ddd;
      left: 0;
      top: 0;
    }
  </style>
</head>

<body>
  <div class="zoom-info">
     <div class="zoom">
       <img src="./2.png" alt="">
      </div>
    <!-- 新增 -->
    <div class="mask"></div>
  </div>
</body>

</html>

视图:

在这里插入图片描述

放大效果图

放大效果图跟原来的图片是一样的,有一个地方不同的是放大效果图的宽高相对于原图是大了一倍,然后父盒子还是跟左边图片一样的宽度,溢出隐藏这样图片放大效果就有了。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    .zoom-info {
      width: 400px;
      height: 400px;
      border: 1px solid pink;
    }

    .zoom-info .zoom img {
      width: 100%;
      height: 100%;
      position: relative;
    }

    .zoom-info .mask {
      width: 200px;
      height: 200px;
      background: rgba(255, 255, 255, 0.5);
      position: absolute;
      border: 1px solid #ddd;
      left: 0;
      top: 0;
    }

    /* 新增 */
    .zoom-info .big-img {
      width: 400px;
      height: 400px;
      position: absolute;
      border: 1px solid #ddd;
      left: 420px;
      top: 0;
      overflow: hidden;
    }

    /* 新增 */
    .zoom-info .big-img img {
      width: 800px;
      height: 800px;
    }
  </style>
</head>

<body>
  <div class="zoom-info">
      <div class="zoom">
       <img src="./2.png" alt="">
      </div>
    <div class="mask"></div>
    <!-- 新增 -->
    <div class="big-img">
      <img src="./2.png" alt="">
    </div>
  </div>
</body>

</html>

视图:

在这里插入图片描述

逻辑设计

蒙版跟放大的图肯定要先隐藏

这里给相关的类名加一个display:none属性就行了

鼠标移入图片显示蒙版

给图片加一个mousemove事件,鼠标移入调整display: block就行了

上脚本代码

  <script>
    window.addEventListener('load', () => {
      // 原始图片 .zoom div
      const originDom = document.querySelector('.zoom')
      console.log(originDom)
      // 正方形蒙版
      const maskDom = document.querySelector('.mask')
      // 大图
      const bigImgDom = document.querySelector('.big-img')
      originDom.addEventListener('mousemove', () => {
        maskDom.style.display = 'block'
        bigImgDom.style.display = 'block'
      })
    })
  </script>

亲测没问题,不贴视图了

鼠标移动蒙版跟着移动

鼠标移动的时候,正方形蒙版肯定也要跟着移动,因为蒙版的中心位置肯定是鼠标,上这部分的处理逻辑,这个地方要说明一个东西,就是鼠标移动的时候,肯定要动态改变蒙版的lefttop值,怎么改呢?看示意图

在这里插入图片描述

注意这个地方不理解好,你后面的东西做不了,这个地方理解了你就没啥大问题了对于放大镜。

写到这里,有一件非常重要的事情,这时候你要回头给一个地方添加css属性,就是给蒙版加一个pointer-events: none;,为什么呢,请参考一下这篇文章,当前你也可以选择不加,后面看看会出什么样的bug再解决也不迟。

  <script>
    window.addEventListener('load', () => {
      // 原始图片 .zoom div
      const originDom = document.querySelector('.zoom')
      console.log(originDom)
      // 正方形蒙版
      const maskDom = document.querySelector('.mask')
      // 大图
      const bigImgDom = document.querySelector('.big-img')
      originDom.addEventListener('mousemove', (e) => {
        maskDom.style.display = 'block'
        bigImgDom.style.display = 'block'
        // 获取鼠标到图片左侧,上侧的位移
        const { offsetX, offsetY } = e
        // 获取蒙版的宽
        const maskWidth = maskDom.offsetWidth
        // 获取蒙版的高
        const maskHeight = maskDom.offsetHeight
        // 计算left的值
        let left = offsetX - maskWidth / 2
        // 计算top的值
        let top = offsetY - maskHeight / 2
        // 赋值
        maskDom.style.left = `${left}px`
        maskDom.style.top = `${top}px`
      })
    })
  </script>

这样鼠标移动的时候蒙版也会跟着移动了

处理边界情况

这个时候会有这么一个问题,就是蒙版会超出img容器,示例

=在这里插入图片描述

所以要处理边界情况:

        // 处理左边和顶部溢出
        if (left < 0) {
          left = 0
        }
        if (top < 0) {
          top = 0
        }
        // 处理右边和下边溢出,left + 蒙版的宽不能大于整个图片容器宽
        if ((left + maskWidth) >= originDom.offsetWidth) {
          left = originDom.offsetWidth - maskWidth
        }
        // top + 蒙版的高不能大于整个图片容器高
        if ((top + maskHeight) >= originDom.offsetHeight) {
          top = originDom.offsetHeight - maskHeight
        }

大图移动

这里注意一点,你想想看,鼠标向左移动,实际上大图要跟着向右移动,为啥呢?因为大图向右移动,我们才能看到大图左边的东西呀,哈哈哈,

这个地方要搞清楚,不然会一脸懵逼,而且还有一点要注意的是你要移动的是图片,而不是大图外层的div,因为外层div是溢出隐藏的,注意,注意,注意记得回头给大图img标签一个绝对定位的属性,不然你的left,top是不生效的。还有一个要注意的地方就是大图移动的距离你可以根据比例来计算。上代码。

        // 比例为大图在父div容器可以移动的距离除以蒙版在小图可以移动的距离
        const ratio = (bigImg.offsetWidth - bigImgDom.offsetWidth) / (originDom.offsetWidth - maskWidth)
        const bigImgLeft = left * ratio
        const bigImgTop = top * ratio
        // 大图移动
        bigImg.style.left = `-${bigImgLeft}px`
        bigImg.style.top = `-${bigImgTop}px`

小优化

代码写到这里,放大镜基本上已经完成了,我们来做一些小优化,鼠标移除原始图片的时候,肯定要,把正方形蒙版和大图隐藏,所以上代码

    // 监听鼠标移除事件    
originDom.addEventListener('mouseleave', () => {
        maskDom.style.display = 'none'
        bigImgDom.style.display = 'none'
      })

然后我们给鼠标移入原始图片加一个小手手的样式,更好看一点

    .zoom-info {
      width: 400px;
      height: 400px;
      border: 1px solid pink;
      cursor: pointer;
    }

终版

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>原生js实现放大镜效果</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    .zoom-info {
      width: 400px;
      height: 400px;
      border: 1px solid pink;
      position: relative;
    }

    .zoom-info .zoom {
      width: 400px;
      height: 400px;
      cursor: pointer;
      position: relative;
    }

    .zoom-info .zoom img {
      width: 100%;
      height: 100%;
      position: relative;
      vertical-align: top;
    }

    .zoom-info .mask {
      width: 200px;
      height: 200px;
      background: rgba(255, 255, 255, 0.5);
      position: absolute;
      left: 0;
      top: 0;
      display: none;
      pointer-events: none;

    }

    .zoom-info .big-img {
      width: 400px;
      height: 400px;
      position: absolute;
      border: 1px solid #ddd;
      left: 420px;
      top: 0;
      overflow: hidden;
      display: none;
    }

    .zoom-info .big-img img {
      width: 800px;
      height: 800px;
      position: absolute;
    }
  </style>
</head>

<body>
  <div class="zoom-info">
    <div class="zoom">
      <img src="./2.png" alt="">
    </div>
    <div class="mask"></div>
    <div class="big-img">
      <img src="./2.png" alt="" class="big">
    </div>
  </div>
  <script>
    let originDom, maskDom, bigImg = null
    window.addEventListener('load', () => {
      // 原始图片 .zoom div
      originDom = document.querySelector('.zoom')

      // 正方形蒙版
      maskDom = document.querySelector('.mask')
      // 大图div
      bigImgDom = document.querySelector('.big-img')
      // 大图图片img标签
      bigImg = document.querySelector('.big')
      handleMouseMove()
      handleMouseLeave()
    })
    // 处理鼠标移动
    function handleMouseMove() {
      originDom.addEventListener('mousemove', (e) => {
        maskDom.style.display = 'block'
        bigImgDom.style.display = 'block'

        // 获取鼠标到图片左侧,上侧的位移
        const {
          offsetX,
          offsetY
        } = e
        // 获取蒙版的宽
        const maskWidth = maskDom.offsetWidth
        // 获取蒙版的高
        const maskHeight = maskDom.offsetHeight
        // 计算left的值

        let left = offsetX - maskWidth / 2
        // 计算top的值
        let top = offsetY - maskHeight / 2
        // 处理左边和顶部溢出
        if (left < 0) {
          left = 0
        }
        if (top < 0) {
          top = 0
        }
        // 处理右边和下边溢出,left + 蒙版的宽不能大于整个图片容器宽
        if ((left + maskWidth) >= originDom.offsetWidth) {
          left = originDom.offsetWidth - maskWidth
        }
        // top + 蒙版的高不能大于整个图片容器高
        if ((top + maskHeight) >= originDom.offsetHeight) {
          top = originDom.offsetHeight - maskHeight
        }
        // 赋值
        maskDom.style.left = `${left}px`
        maskDom.style.top = `${top}px`
        // 比例为大图在父div容器可以移动的距离除以蒙版在小图可以移动的距离
        const ratio = (bigImg.offsetWidth - bigImgDom.offsetWidth) / (originDom.offsetWidth - maskWidth)
        const bigImgLeft = left * ratio
        const bigImgTop = top * ratio
        // 大图移动
        bigImg.style.left = `-${bigImgLeft}px`
        bigImg.style.top = `-${bigImgTop}px`
      })
    }
    // 处理鼠标离开
    function handleMouseLeave() {
      originDom.addEventListener('mouseleave', () => {
        maskDom.style.display = 'none'
        bigImgDom.style.display = 'none'
        // 解绑事件
        originDom.onmousemove = null
        originDom.obmouseleave = null
      })
    }
  </script>
</body>

</html>

注意注意注意直接复制粘贴该html代码是运行不了的,因为图片你是没有的哈,记得自己弄2张图片!!!。

博客

欢迎访问我的博客www.smartxy.cc

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值