Skip to content

图片放大镜

思路

准备三张图片,小-中-大。

小图:缩略图,用于展示缩略部分。

中图:展示的图片,放大镜滑动的底图。

大图:放大区域的图片。

核心点:

放大镜跟随鼠标移动,并且鼠标永远处于正中间。

放大镜边界区域判断

根据鼠标移动的x,y的偏移量,同步大图的背景的偏移量。

1. 初始化

  • 动态生成图片的缩略图

  • 默认选中第一个元素

2. 交互

  • 鼠标mousemove事件:

    计算遮罩层位置

    鼠标x - 图片左侧距离 - 放大镜宽度/2

    js
    // 根据鼠标位置计算遮罩层的位置
     var left = e.clientX - midImg.offsetLeft - mask.offsetWidth / 2;
    // 同理
     var top = e.clientY - midImg.offsetTop - mask.offsetHeight / 2;

    移动边界判断

    x,y方向最小: 0

    x,y最大: 图片自身宽度/高度 - 遮罩层自身宽度/高度

    同步放大区域的偏移量

    放大区域的背景图位置就是上面计算出来的遮罩层的left和top,同步即可。

  • 鼠标移出mouseleave

    隐藏遮罩层和大图区域

  • 点击缩略图

    替换底图和大图

代码实现

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>
  <link rel="stylesheet" href="./index.css">
</head>
<body>
  <!--最外层容器 -->
  <div class="container">
    <!-- 左侧原图 -->
    <div class="left-img">
      <!-- 遮罩层 -->
      <div class="mask"></div>
    </div>
    <!-- 右侧放大图片 -->
    <div class="right-img"></div>
    <!-- 缩略图集合 -->
    <div class="img-list-wrapper">
      <ul class="img-list">
      </ul>
    </div>
  </div>
  <script src="./index.js"></script>
</body>
</html>
css
* {
  margin: 0;
  padding: 0;
  list-style: none;
}

.container {
  width: 1000px;
  height: 600px;
  margin: 50px auto;
  font-size: 0;
}

.left-img {
  width: 490px;
  height: 510px;
  margin-right: 16px;
  border: 1px solid #eee;
  display: inline-block;
  /* 图片 */
  background-image: url(./images/imgA_2.jpg);
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
  /* 遮罩层相对我进行定位 */
  position: relative;
}
.mask {
  width: 230px;
  height: 230px;
  background-image: url(./images/bg.png);
  position: absolute;
  top: 0;
  left: 0;
  opacity: 0;
}
.right-img {
  width: 490px;
  height: 510px;
  border: 1px solid #eee;
  display: inline-block;
  background-image: url(./images/imgA_3.jpg);
  background-repeat: no-repeat;
  opacity: 0;
}

.img-list-wrapper {
  width: 490px;
  text-align: center;
  margin-top: 10px;
}
.img-list {
  display: inline-block;
}
.img-list li {
  display: inline-block;
  width: 60px;
  height: 60px;
  margin: 0 5px;
  cursor: pointer;
  /* background-image: url(./images/imgA_1.jpg); */
  background-repeat: no-repeat;
  /* border: 2px solid #000; */
  border: 1px solid #eee;
}
js

/* 工具 */
// 单一元素
function $(selector) {
  return document.querySelector(selector);
}

// 多个元素
function $$(selector) {
  return document.querySelectorAll(selector);
}


/* 初始化 */
var imgs = {
  // 小图
  small: ['imgA_1.jpg', 'imgB_1.jpg', 'imgC_1.jpg'],
  // 中图
  middle: ['imgA_2.jpg', 'imgB_2.jpg', 'imgC_2.jpg'],
  // 大图
  large: ['imgA_3.jpg', 'imgB_3.jpg', 'imgC_3.jpg']
}

// 获取一些将要使用的dom元素
var container = $('.container');
var largeImg = $('.right-img');
var midImg = $('.left-img');
var smallImg = $('.img-list');
var mask = $('.mask');


// 初始化页面函数
function initPage() {
  var str = '';
  for (var i = 0; i < imgs.small.length; i++) {
    str += '<li style="background-image: url(./images/' + imgs.small[i] + ');"></li>'
  }
  smallImg.innerHTML = str;
  // 2. 默认选中第一个缩略图
  $('.img-list li').style.border = '2px solid #000';
}


/* 交互 */
// 绑定事件
function bindEvent() {
  // 点击缩略图
  smallImg.onclick = function (e) {
    // 判断我点击的元素是li元素
    if (e.target.tagName == 'LI') {
      // 让所有li元素取消border
      var lis = $$('li');
      for (var i = 0; i < lis.length; i++) {
        lis[i].style.border = 'none';
      }
      // 让选中的li元素添加border
      e.target.style.border = '2px solid #000';

      // 点击缩略图后,原图和大图也需要跟着变换,
      // 点的是第几个元素, 获取元素索引
      // [1,2,3].indexOf(3) == 2
      var index = [].indexOf.call(lis, e.target);
      midImg.style.backgroundImage = 'url(./images/' + imgs.middle[index] + ')';
      largeImg.style.backgroundImage = 'url(./images/' + imgs.large[index] + ')';
    }
  }

  // 鼠标移入
  midImg.onmousemove = function (e) {
    // 让遮罩层和大图展示
    mask.style.opacity = 1;
    largeImg.style.opacity = 1;

    // 根据鼠标位置计算遮罩层的位置
    var left = e.clientX - midImg.offsetLeft - mask.offsetWidth / 2;
    // 同理
    var top = e.clientY - midImg.offsetTop - mask.offsetHeight / 2;

    // 边界条件
    if (left <= 0) {
      left = 0;
    }
    if (top <= 0) {
      top = 0;
    }
    if (left >= midImg.offsetWidth - mask.offsetWidth) {
      left = midImg.offsetWidth - mask.offsetWidth
    }
    if (top >= midImg.offsetHeight - mask.offsetHeight) {
      top = midImg.offsetHeight - mask.offsetHeight
    }
    // 根据top和left调整mask的位置
    mask.style.left = left + 'px';
    mask.style.top = top + 'px';

    // 根据top 和 left,修改大图的位置,background-position-x
    largeImg.style.backgroundPositionX = -left + 'px';
    largeImg.style.backgroundPositionY = -top + 'px';

  }

  // 鼠标移出
  midImg.onmouseleave = function (e) {
    // 让遮罩层和大图消失
    mask.style.opacity = 0;
    largeImg.style.opacity = 0;
  }
}

function main() {
  initPage();
  bindEvent();
}

main();

MIT License