原生JS实现放大镜效果并可随鼠标滚轮事件实现二次放大

概述

  1. 基本放大镜效果
  • 首先是放大镜的追随效果,通过在原图注册的onmousemove事件获取事件的clientYclientX配合其它参数值计算出放大镜在其父元素:原图的topleft属性的值。
  • 放大图中的图片的margin-topmargin-left属性去上面topleft的相反值
  1. 二次放大效果
  • 为原图注册onmousewheel事件获取事件的wheeldelta判断放大还是缩小,配合CSS3的transform属性的scale()

代码

首先先介绍一个简单的工具函数 封装工具函数原文

封装工具函数

//返回元素对象到浏览器窗口偏移量
function offset(obj, direction) {
      var offsetDir = 'offset' + direction[0].toUpperCase() + direction.substring(1);
      var realNum = obj[offsetDir];
      var positionParent = obj.offsetParent;
      while (positionParent != null) {
        realNum += positionParent[offsetDir];
        positionParent = positionParent.offsetParent;
      }
      return realNum;
    }

下面是完整代码


<html lang="zh-cn">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>放大镜3.0title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    .picture {
      position: relative;
      width: 400px;
      height: 200px;
      margin: 50px auto;
    }
    .picture img {
      width: 100%;
      height: 100%;
    }
    .showPic {
      width: 350px;
      height: 350px;
      margin: 50px auto;
      overflow: hidden;
    }
    .glass {
      position: absolute;
      box-sizing: border-box;
      width: 50px;
      height: 50px;
      background-color: #fff;
      opacity: 0.3;
      border: 1px solid #ddd;
      /* display: none; */
      visibility: hidden;
      cursor: move;
    }
  style>
head>

<body>
  <div class="picture">
    <img src="img/lunbo.jpg" alt="">
    <div class="glass">div>
  div>
  <div class="showPic">
    <img src="img/lunbo.jpg" alt="">
  div>
  <script>
    //返回元素对象到浏览器窗口偏移量
    function offset(obj, direction) {
      var offsetDir = 'offset' + direction[0].toUpperCase() + direction.substring(1);
      var realNum = obj[offsetDir];
      var positionParent = obj.offsetParent;
      while (positionParent != null) {
        realNum += positionParent[offsetDir];
        positionParent = positionParent.offsetParent;
      }
      return realNum;
    }
    // --------------------------------------------------------
    // 获取元素
    var pic = document.getElementsByClassName('picture')[0],
        showPic = document.getElementsByClassName('showPic')[0],
        showImg = showPic.children[0],
        glass = document.getElementsByClassName('glass')[0];
    //获取图像盒子到浏览器窗口偏移量
    var picTop = offset(pic, 'top');
    var picLeft = offset(pic, 'left');
    //获取元素实际高度宽度
    var picWidth = pic.offsetWidth;
        picHeight = pic.offsetHeight,
        glassWidth = glass.offsetWidth, 
        glassHeight = glass.offsetHeight, 
        showPicWidth = showPic.offsetWidth,
        showPicHeight = showPic.offsetHeight;

    var showImgWidth, showImgHeight;
    //等图片加载完成后才可以获取图片实际宽度高度
    showImg.onload = function () {
      showImgWidth = showImg.width;
      showImgHeight = showImg.height;
      console.log(showImgWidth, showImgHeight)
    }
    //调试
    // console.log(picWidth, picHeight, glassWidth, glassHeight, showPicWidth, showPicHeight, showImgWidth, showImgHeight)

    //放大镜glass元素显示与跟随
    pic.onmousemove = function (e) {
      var ctrlTop = e.clientY - picTop - glassHeight / 2;
      var ctrlLeft = e.clientX - picLeft - glassWidth / 2;
      //控制glass元素top、left属性在盒子四边的边界值
      if (ctrlTop < 0) {
        ctrlTop = 0;
      } else if (ctrlTop > picHeight - glassHeight) {
        ctrlTop = picHeight - glassHeight;
      }
      if (ctrlLeft < 0) {
        ctrlLeft = 0;
      } else if (ctrlLeft > picWidth - glassWidth) {
        ctrlLeft = picWidth - glassWidth;
      }
      glass.style.top = ctrlTop + 'px';
      glass.style.left = ctrlLeft + 'px';
      glass.style.visibility = 'visible';
      // console.log(ctrlLeft, ctrlTop);

      //实现showPic元素追随并放大内容显示
      //防止图片不能铺满盒子而留有空白的视觉效果
      if (ctrlTop > showImgHeight - showPicHeight) {
        ctrlTop = showImgHeight - showPicHeight;
      }
      if (ctrlLeft > showImgWidth - showPicWidth) {
        ctrlLeft = showImgWidth - showPicWidth;
      }
      showImg.style.marginTop = -ctrlTop + 'px';
      showImg.style.marginLeft = -ctrlLeft + 'px';
    }

    //还原默认效果
    pic.onmouseout = function () {
      glass.style.visibility = 'hidden';
      showImg.style.transform = 'none';
    }

    //鼠标滚轮二次放大效果
    var scale = 1;
    pic.onmousewheel = function (event) {
      event = event || window.event;
      if (event.wheelDelta > 0) {
        scale += 0.1;
        if (scale > 5) {
          scale = 5;
        }
      } else {
        scale += -0.1;
        if (scale < 0.5) {
          scale = 0.5;
        }
      }
      showImg.style.transform = 'scale(' + scale  + ')';
      event.preventDefault(); // 阻止默认事件 即滚动条滚动 
      // console.log(scale); 
    }
  script>

body>

html>

其它

  • glass元素默认如果不设置visibility: hidden设置display:none的话要通过window.getComputedStyle()方法来获取它们的宽高(内容宽高度,带单位)
  • img元素需要onload完成后才能直接获取它们宽高
  • 鼠标滚轮二次放大时候 用事件preventDefault()方法,阻止默认事件滚动条滚动发生

你可能感兴趣的:(JavaScript)