js图片局部放大镜效果

js实现放大镜,先来看效果

鼠标移动到左侧区域,右侧区域放大图片对应的位置

首先来看html部分,一共由3个div组成

html 复制代码
  <!-- 图片盒子 -->
  <div class="box">
    <!-- 放大镜 -->
    <div class="area"></div>
  </div>
  <!-- 放大后的区域 -->
  <div class="zoom-content"></div>

下面来编写一下css

css 复制代码
    .box{
      display: inline-block;
      position: relative;
      width:400px;
      height:400px;
      border:1px solid red;
      background-image: url('https://img2.baidu.com/it/u=3663343515,2094544376&fm=253&fmt=auto&app=138&f=PNG?w=400&h=400');
      background-size: 100% 100%;
      vertical-align: top;
    }
    .area{
      position: absolute;
      width:200px;
      height:200px;
      background-color: rgba(0, 0, 255,.5);
      cursor: move;
    }
    .zoom-content{
      display: inline-block;
      width:500px;
      height:500px;
      border:1px solid red;
      background-image: url('https://img2.baidu.com/it/u=3663343515,2094544376&fm=253&fmt=auto&app=138&f=PNG?w=400&h=400');
      background-repeat: no-repeat;
    }

编写完成后如图 下面开始js逻辑部分

1.我们首先开始实现第一个功能,鼠标移入框内后,让蓝色的盒子(放大镜)跟着鼠标移动

js 复制代码
    // 先获取DOM元素
    
    let area = document.querySelector('.area'); // 放大镜
    let box = document.querySelector('.box'); // 图片盒子
    let zoom = document.querySelector('.zoom-content'); //右侧放大区域
    
    // 放大镜蓝色背景盒子尺寸
    let areaWidth = area.clientWidth;
    let areaHeight = area.clientHeight;
    // 鼠标移入后的事件
    const enter = (event) => {
      // 设置放大镜的位置
      setAreaPosition(event);
      box.addEventListener("mousemove",move);
      box.addEventListener("mouseleave",leave);
    }
    // 鼠标移动事件    
    const move = (event) => {
      setAreaPosition(event);
    }
    //鼠标移出后 取消绑定一下
    const leave = () => {
      box.removeEventListener("mousemove",move);
      box.removeEventListener("mouseleave",leave);
    }
    // 设置放大镜的位置
    const setAreaPosition = (event) => {
      // 让放大镜垂直居中显示在鼠标移动后的位置 需减去自身方向的一半
      let x = event.x - areaWidth / 2;
      let y = event.y - areaHeight / 2;
      area.style.left = x+"px";
      area.style.top = y+"px";
    }
    box.addEventListener("mouseenter",enter);

这样就能让放大镜跟随鼠标移动了,但是有点瑕疵,需要让放大镜一直保持在盒子里面,需要判断一下距离边界情况

js 复制代码
    // 图片盒子大小尺寸
    let boxWidth = box.clientWidth;
    let boxHeight = box.clientHeight;
    // 放大镜X轴极限距离
    let maxX = boxWidth - areaWidth;
    // 放大镜Y轴极限距离
    let maxY = boxHeight - areaHeight;

maxX,maxY就是边界的距离,我们需要在setAreaPosition函数中,对x轴,y轴的大小做一下限制

js 复制代码
    const setAreaPosition = (event) => {
      // 让放大镜垂直居中显示在鼠标移动后的位置 需减去自身方向的一半
      let x = event.x - areaWidth / 2;
      let y = event.y - areaHeight / 2;
      // x的值不能大于maxX,同时不能小于0,y的判断同理
      x = Math.min(maxX,Math.max(0,x));
      // y的值不能大于maxY,同时不能小于0
      y = Math.min(maxY,Math.max(0,y));
      area.style.left = x+"px";
      area.style.top = y+"px";
    }

通过Math.min方法和Math.max方法就能对x,y极限值做限制了

下面我们来设置一下右侧放大区域,目前来看它并没有放大,而是保持了图片本来的大小,下面是js部分

js 复制代码
    // 先获取一下缩放的倍率,也就是放大镜和图片盒子做对比
    // 缩放倍率
    let xScale = boxWidth / areaWidth;
    let yScale = boxHeight / areaHeight;
    // 知道了倍率后,我们对放大区域的图片大小做一下设置
    // 因为使用的是背景图片所以需设置一下backgroundSize属性
    zoom.style.backgroundSize=`${xScale * 100}% ${yScale * 100}%`;

这一部分呢可以理解为把右侧的放大区域(.zoom-content)看作是放大镜(.area);

下面只差最后一部分了,移动鼠标,让右侧放大区域改变,只需要改变(.zoom-content)的backgroundPosition即可

那的backgroundPosition的值怎么计算呢?

绿色背景假设为图片,左侧的蓝色是放大镜,右侧的蓝色是放大后的区域,这样就一目了然了,先算出放大镜距离图片盒子的多少比例,然后在拿这个比例去算出占放大后的背景多少像素就可以了

js 复制代码
    // 缩放后的图片尺寸
    let bgWidth = zoom.clientWidth * xScale;
    let bgHeight = zoom.clientHeight * yScale;

setAreaPosition函数修改一下

js 复制代码
    // 设置放大镜的位置
    const setAreaPosition = (event) => {
      let x = event.x - areaWidth / 2;
      let y = event.y - areaHeight / 2;
      // x的值不能大于maxX,同时不能小于0,y的判断同理
      x = Math.min(maxX,Math.max(0,x));
      // y的值不能大于maxY,同时不能小于0
      y = Math.min(maxY,Math.max(0,y));
      area.style.left = x+"px";
      area.style.top = y+"px";
      // 计算背景距离,为什么为负数,负数图片为往右走,正数为左走
      // x / boxWidth 放大镜距离左侧的比例,根据这个比例 * 相应的图片宽度,就知道图片要走到哪里了
      zoom.style.backgroundPosition = `${-(x / boxWidth * bgWidth)}px ${-(y / boxHeight * bgHeight)}px`;
    }

后续可以在移入和移出时改变(.area)放大镜的visibility就行

js 复制代码
// enter 移入
area.style.visibility = 'visible';
// leave 移出
area.style.visibility = 'hidden';

完整代码如下

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .box{
      display: inline-block;
      position: relative;
      width:400px;
      height:400px;
      border:1px solid red;
      background-image: url('https://img2.baidu.com/it/u=3663343515,2094544376&fm=253&fmt=auto&app=138&f=PNG?w=400&h=400');
      background-size: 100% 100%;
      vertical-align: top;
    }
    .area{
      position: absolute;
      width:200px;
      height:200px;
      background-color: rgba(0, 0, 255,.5);
      visibility: hidden;
      cursor: move;
    }
    .zoom-content{
      display: inline-block;
      width:500px;
      height:500px;
      border:1px solid red;
      background-image: url('https://img2.baidu.com/it/u=3663343515,2094544376&fm=253&fmt=auto&app=138&f=PNG?w=400&h=400');
      background-repeat: no-repeat;
    }
  </style>
</head>
<body>
  <div class="box">
    <div class="area"></div>
  </div>
  <div class="zoom-content"></div>
  <script>
    // 获取DOM元素
    let area = document.querySelector('.area');
    let box = document.querySelector('.box');
    let zoom = document.querySelector('.zoom-content');
    // 蓝色背景盒子尺寸
    let areaWidth = area.clientWidth;
    let areaHeight = area.clientHeight;
    // 图片盒子大小尺寸
    let boxWidth = box.clientWidth;
    let boxHeight = box.clientHeight;
    // 蓝色盒子X轴极限距离
    let maxX = boxWidth - areaWidth;
    // 蓝色盒子Y轴极限距离
    let maxY = boxHeight - areaHeight;
    // 缩放倍率
    let xScale = boxWidth / areaWidth;
    let yScale = boxHeight / areaHeight;
    // 缩放后的图片尺寸
    let bgWidth = zoom.clientWidth * xScale;
    let bgHeight = zoom.clientHeight * yScale;
    zoom.style.backgroundSize=`${xScale * 100}% ${yScale * 100}%`;
    const enter = (event) => {
      area.style.visibility = 'visible';
      setAreaPosition(event);
      box.addEventListener("mousemove",move);
      box.addEventListener("mouseleave",leave);
    }
    const leave = () => {
      area.style.visibility = 'hidden';
      box.removeEventListener("mousemove",move);
      box.removeEventListener("mouseleave",leave);
    }
    const setAreaPosition = (event) => {
      let x = event.x - areaWidth / 2;
      let y = event.y - areaHeight / 2;
      x = Math.min(maxX,Math.max(0,x));
      y = Math.min(maxY,Math.max(0,y));
      area.style.left = x+"px";
      area.style.top = y+"px";
      zoom.style.backgroundPosition = `${-(x / boxWidth * bgWidth)}px ${-(y / boxHeight * bgHeight)}px`;
    }
    const move = (event) => {
      setAreaPosition(event);
    }
    box.addEventListener("mouseenter",enter)
  </script>
</body>
</html>
相关推荐
滚雪球~3 分钟前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语5 分钟前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js
supermapsupport6 分钟前
iClient3D for Cesium在Vue中快速实现场景卷帘
前端·vue.js·3d·cesium·supermap
brrdg_sefg8 分钟前
WEB 漏洞 - 文件包含漏洞深度解析
前端·网络·安全
胡西风_foxww15 分钟前
【es6复习笔记】rest参数(7)
前端·笔记·es6·参数·rest
m0_7482548816 分钟前
vue+elementui实现下拉表格多选+搜索+分页+回显+全选2.0
前端·vue.js·elementui
星就前端叭1 小时前
【开源】一款基于Vue3 + WebRTC + Node + SRS + FFmpeg搭建的直播间项目
前端·后端·开源·webrtc
m0_748234521 小时前
前端Vue3字体优化三部曲(webFont、font-spider、spa-font-spider-webpack-plugin)
前端·webpack·node.js
Web阿成1 小时前
3.学习webpack配置 尝试打包ts文件
前端·学习·webpack·typescript
jwensh2 小时前
【Jenkins】Declarative和Scripted两种脚本模式有什么具体的区别
运维·前端·jenkins