API-案例-放大镜效果

学习目标:

  • 掌握案例-放大镜效果

学习内容:

  1. 业务分析
  2. 思路分析
  3. 放大镜完整代码

业务分析:

  • 鼠标经过对应小盒子,左侧中等盒子显示对应中等图片;
  • 鼠标经过中盒子,右侧会显示放大镜效果的大盒子;
  • 黑色遮罩盒子跟着鼠标来移动;
  • 鼠标在中等盒子上移动,大盒子的图片跟着显示对应位置。

思路分析:

  • 鼠标经过小盒子,左侧中等盒子显示对应中等图片:
  1. 获取对应的元素。

  2. 采取事件委托的形式,监听鼠标经过小盒子里面的图片, 注意此时需要使用 mouseover 事件,因为需要事件冒泡触发small

  3. 让鼠标经过小图片的爸爸li盒子,添加类,其余的li移除类(注意先移除,后添加)。

  4. 鼠标经过小图片,可以拿到小图片的src, 可以做两件事:

    让中等盒子的图片换成这个 这个小图片的src
    让大盒子的背景图片,也换成这个小图片的 src (稍后做)
    
//获取三个盒子
    //2.小盒子 图片切换效果
    const small = document.querySelector('.small')
    //中盒子
    const middle = document.querySelector('.middle')
    //大盒子
    const large = document.querySelector('.large')
    //2.事件委托
    small.addEventListener('mouseover', function (e) {
      if (e.target.tagName === 'IMG') {
        // console.log(11)
        //排他  干掉以前的active li  上面
        this.querySelector('.active').classList.remove('active')
        //当前元素的爸爸添加active
        e.target.parentNode.classList.add('active')
        //拿到当前小图片的src
        // console.log(e.target.src)
        //让中盒子里面的图片 ,src更换为  小图片src
        middle.querySelector('img').src = e.target.src
        //大盒子更换背景图片
        large.style.backgroundImage = `url(${e.target.src})`
      }

    })
  • 鼠标经过中等盒子,右侧大盒子显示:
  1. 用到鼠标经过和离开,鼠标经过中盒子,大盒子 利用 display 来显示和隐藏。
  2. 鼠标离开不会立马消失,而是有200ms的延时,用户体验更好,所以尽量使用定时器做个延时 setTimeout
  3. 显示和隐藏也尽量定义一个函数,因为鼠标经过离开中等盒子,会显示隐藏,同时,鼠标经过大盒子,也会显示和隐藏。
  4. 给大盒子里面的背景图片一个默认的第一张图片。
 //3.鼠标经过中等盒子,显示隐藏  大盒子
    middle.addEventListener('mouseenter', show)
    middle.addEventListener('mouseleave', hide)
    let timeId = null
    //显示函数  显示大盒子
    function show() {
      //先清除定时器
      clearTimeout(timeId)
      large.style.display = 'block'
    }
    //隐藏函数  隐藏大盒子
    function hide() {
      timeId = setTimeout(function () {
        large.style.display = 'none'
      }, 200)
    }

  • 黑色遮罩盒子跟着鼠标来移动:
  1. 先做鼠标经过中等盒子,显示隐藏黑色遮罩的盒子。
  2. 让黑色遮罩跟着鼠标来走, 需要用到鼠标移动事件 mousemove
  3. 让黑色盒子的移动的核心思想:不断把鼠标在中等盒子内的坐标给黑色遮罩层 let top 值,这样遮罩层就可以跟着移动了。

需求
我们要的是鼠标在中等盒子内的坐标, 没有办法直接得到。
得到1: 鼠标在页面中的坐标。
得到2: 中等盒子在页面中的坐标

算法
得到鼠标在页面中的坐标 利用事件对象的 pageX
得到middle中等盒子在页面中的坐标 middle.getBoundingClientRect()
鼠标在middle 盒子里面的坐标 = 鼠标在页面中的坐标 - middle 中等盒子的坐标。
黑色遮罩层不断得到 鼠标在middle 盒子中的坐标 就可以移动起来了。

注意 y坐标特殊,需要减去 页面被卷去的头部
为什么不用 box.offsetLet 和 box.offsetTop 因为这俩属性跟带有定位的父级有关系,很容被父级影响,而getBoundingClientRect() 不受定位的父元素的影响

限定遮罩的盒子只能在middle 内部移动,需要添加判断:
限定水平方向 大于等于0 并且小于等于 400。
限定垂直方向 大于等于0 并且小于等于 400。

遮罩盒子移动的坐标
声明一个 mx 作为移动的距离。
水平坐标 x 如果 小于等于100 ,则移动的距离 mx 就是 0 不应该移动
水平坐标 如果 大于等于100 并且小于300,移动的距离就是 mx - 100 (100是遮罩盒子自身宽度的一半)
水平坐标 如果 大于等于300,移动的距离就是 mx 就是200 不应该在移动了
其实我们发现水平移动, 就在 100 ~ 200 之间移动的。
垂直同理。

let mx = 0, my = 0;
if (x <= 100) mx = 0
if (x > 100 && x < 300) mx = x - 100
if (x >= 300) mx = 200

if (y <= 100) my = 0
if (y > 100 && y < 300) my = y - 100
if (y >= 300) my = 200

大盒子图片移动的计算方法
中等盒子是 400px 大盒子 是 800px 的图片。
中等盒子移动1px, 大盒子就应该移动2px, 只不过是负值。

large.style.backgroundPositionX = - 2 * mx + 'px'
large.style.backgroundPositionY = - 2 * my + 'px'
//4.鼠标经过大盒子,显示隐藏 大盒子
    large.addEventListener('mouseenter', show)
    large.addEventListener('mouseleave', hide)

    //5.鼠标经过中等盒子,显示隐藏 黑色遮罩层
    const layer = document.querySelector('.layer')
    middle.addEventListener('mouseenter', function () {
      layer.style.display = 'block'
    })
    middle.addEventListener('mouseleave', function () {
      layer.style.display = 'none'
    })

    //6.移动盒子遮罩盒子
    middle.addEventListener('mousemove', function (e) {
      // let x = 20, y = 20
      // console.log(11)
      //鼠标在middle盒子里面的坐标 = 鼠标在页面中的坐标 - middle中等盒子的坐标
      // console.log(e.pageX)鼠标在页面中的坐标
      //middle 中等盒子的坐标
      // console.log(middle.getBoundingClientRect().left)
      let x = e.pageX - middle.getBoundingClientRect().left
      let y = e.pageY - middle.getBoundingClientRect().top - document.documentElement.scrollTop
      // console.log(x, y)
      //黑色遮罩移动 在middle盒子内  限定移动的距离
      if (x >= 0 && x <= 400 && y >= 0 && y <= 400) {
        //黑色盒子不是一直移动的
        //声明2个变量  黑色盒子移动的 mx my变量
        let mx = 0, my = 0
        if (x < 100) mx = 0
        if (x >= 100 && x <= 300) mx = x - 100
        if (x > 300) mx = 200

        if (y < 100) my = 0
        if (y >= 100 && y <= 300) my = y - 100
        if (y > 300) my = 200

        layer.style.left = mx + 'px'
        layer.style.top = my + 'px'
        //大盒子的背景图片要跟随 中等盒子移动  存在的关系是2倍
        large.style.backgroundPositionX = -2 * mx + 'px'
        large.style.backgroundPositionY = -2 * my + 'px'

      }

放大镜完整代码:

<script>
    //获取三个盒子
    //2.小盒子 图片切换效果
    const small = document.querySelector('.small')
    //中盒子
    const middle = document.querySelector('.middle')
    //大盒子
    const large = document.querySelector('.large')
    //2.事件委托
    small.addEventListener('mouseover', function (e) {
      if (e.target.tagName === 'IMG') {
        // console.log(11)
        //排他  干掉以前的active li  上面
        this.querySelector('.active').classList.remove('active')
        //当前元素的爸爸添加active
        e.target.parentNode.classList.add('active')
        //拿到当前小图片的src
        // console.log(e.target.src)
        //让中盒子里面的图片 ,src更换为  小图片src
        middle.querySelector('img').src = e.target.src
        //大盒子更换背景图片
        large.style.backgroundImage = `url(${e.target.src})`
      }

    })

    //3.鼠标经过中等盒子,显示隐藏  大盒子
    middle.addEventListener('mouseenter', show)
    middle.addEventListener('mouseleave', hide)
    let timeId = null
    //显示函数  显示大盒子
    function show() {
      //先清除定时器
      clearTimeout(timeId)
      large.style.display = 'block'
    }
    //隐藏函数  隐藏大盒子
    function hide() {
      timeId = setTimeout(function () {
        large.style.display = 'none'
      }, 200)
    }

    //4.鼠标经过大盒子,显示隐藏 大盒子
    large.addEventListener('mouseenter', show)
    large.addEventListener('mouseleave', hide)

    //5.鼠标经过中等盒子,显示隐藏 黑色遮罩层
    const layer = document.querySelector('.layer')
    middle.addEventListener('mouseenter', function () {
      layer.style.display = 'block'
    })
    middle.addEventListener('mouseleave', function () {
      layer.style.display = 'none'
    })

    //6.移动盒子遮罩盒子
    middle.addEventListener('mousemove', function (e) {
      // let x = 20, y = 20
      // console.log(11)
      //鼠标在middle盒子里面的坐标 = 鼠标在页面中的坐标 - middle中等盒子的坐标
      // console.log(e.pageX)鼠标在页面中的坐标
      //middle 中等盒子的坐标
      // console.log(middle.getBoundingClientRect().left)
      let x = e.pageX - middle.getBoundingClientRect().left
      let y = e.pageY - middle.getBoundingClientRect().top - document.documentElement.scrollTop
      // console.log(x, y)
      //黑色遮罩移动 在middle盒子内  限定移动的距离
      if (x >= 0 && x <= 400 && y >= 0 && y <= 400) {
        //黑色盒子不是一直移动的
        //声明2个变量  黑色盒子移动的 mx my变量
        let mx = 0, my = 0
        if (x < 100) mx = 0
        if (x >= 100 && x <= 300) mx = x - 100
        if (x > 300) mx = 200

        if (y < 100) my = 0
        if (y >= 100 && y <= 300) my = y - 100
        if (y > 300) my = 200

        layer.style.left = mx + 'px'
        layer.style.top = my + 'px'
        //大盒子的背景图片要跟随 中等盒子移动  存在的关系是2倍
        large.style.backgroundPositionX = -2 * mx + 'px'
        large.style.backgroundPositionY = -2 * my + 'px'
      }
    })
  </script>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/781015.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

传统IO和NIO文件拷贝过程

参考&#xff1a;https://blog.csdn.net/weixin_57323780/article/details/130250582

几个小创新模型,KAN组合网络(LSTM、GRU、Transformer)回归预测,python预测全家桶再更新!...

截止到本期&#xff0c;一共发了9篇关于机器学习预测全家桶Python代码的文章。参考往期文章如下&#xff1a; 1.终于来了&#xff01;python机器学习预测全家桶 2.机器学习预测全家桶-Python&#xff0c;一次性搞定多/单特征输入&#xff0c;多/单步预测&#xff01;最强模板&a…

【网络安全】实验三(基于Windows部署CA)

一、配置环境 打开两台虚拟机&#xff0c;并参照下图&#xff0c;搭建网络拓扑环境&#xff0c;要求两台虚拟的IP地址要按照图中的标识进行设置&#xff0c;并根据搭建完成情况&#xff0c;勾选对应选项。注&#xff1a;此处的学号本人学号的最后两位数字&#xff0c;1学号100…

《python程序语言设计》2018版第5章第52题利用turtle绘制sin函数

这道题是送分题。因为循环方式已经写到很清楚&#xff0c;大家照抄就可以了。 但是如果说光照抄可是会有问题。比如我们来演示一下。 import turtleturtle.penup() turtle.goto(-175, 50 * math.sin((-175 / 100 * 2 * math.pi))) turtle.pendown() for x in range(-175, 176…

k8s学习之cobra命令库学习

1.前言 打开k8s代码的时候&#xff0c;我发现基本上那几个核心服务都是使用cobra库作为命令行处理的能力。因此&#xff0c;为了对代码之后的代码学习的有比较深入的理解&#xff0c;因此先基于这个库写个demo&#xff0c;加深对这个库的一些理解吧 2.cobra库的基本简介 Git…

算法设计与分析 实验5 并查集法求图论桥问题

目录 一、实验目的 二、问题描述 三、实验要求 四、实验内容 &#xff08;一&#xff09;基准算法 &#xff08;二&#xff09;高效算法 五、实验结论 一、实验目的 1. 掌握图的连通性。 2. 掌握并查集的基本原理和应用。 二、问题描述 在图论中&#xff0c;一条边被称…

IDEA发疯导致maven下载回来的jar不完整zip END header not found

IDEA发疯导致maven下载回来的jar不完整zip END header not found 具体报错 java: 读取D:\mavenRepository\com\alibaba\druid-spring-boot-starter\1.2.23\druid-spring-boot-starter-1.2.23.jar时出错; zip END header not foundjava: java.lang.RuntimeException: java.io.…

Python视觉轨迹几何惯性单元超维计算结构算法

&#x1f3af;要点 &#x1f3af;视觉轨迹几何惯性单元超维计算结构算法 | &#x1f3af;超维计算结构视觉场景理解 | &#x1f3af;超维计算结构算法解瑞文矩阵 | &#x1f3af;超维矢量计算递归神经算法 &#x1f36a;语言内容分比 &#x1f347;Python蒙特卡罗惯性导航 蒙…

【感谢告知】本账号内容调整,聚焦于Google账号和产品的使用经验和问题案例分析

亲爱的各位朋友&#xff1a; 感谢您对本账号的关注和支持&#xff01; 基于对朋友们需求的分析和个人兴趣的转变&#xff0c;该账号从今天将对内容做一些调整&#xff0c;有原来的内容改为Google&#xff08;谷歌&#xff09;账号和产品的使用经验&#xff0c;以及相关问题的…

LeetCode 744, 49, 207

目录 744. 寻找比目标字母大的最小字母题目链接标签思路代码 49. 字母异位词分组题目链接标签思路代码 207. 课程表题目链接标签思路代码 744. 寻找比目标字母大的最小字母 题目链接 744. 寻找比目标字母大的最小字母 标签 数组 二分查找 思路 本题比 基础二分查找 难的一…

《python程序语言设计》2018版第5章第53题利用turtle绘制sin和cos函数 sin蓝色,cos红色和52题类似

直接上题和代码 5.53 &#xff08;Turtle&#xff1a;绘制sin和cos函数&#xff09;编写程序绘制蓝色的sin函数和红色的cos函数。 代码和结果 turtle.speed(10) turtle.penup() # sin 用蓝色 turtle.color("blue") #这道题和上道题一样&#xff0c;先把turtle放到起始…

pandas读取CSV格式文件生成数据发生器iteration

背景 数据集标签为csv文件格式&#xff0c;有三个字段column_hander [‘id’, ‘boneage’, ‘male’]&#xff0c;需要自己定义数据集。文件较大&#xff0c;做一个数据发生器迭代更新数据集。 实现模板 在Pandas中&#xff0c;可以使用pandas.read_csv函数读取CSV文件&…

官网首屏:激发你的小宇宙和第六感,为了漂亮,干就完了。

官网的首屏是指用户打开网站后首先看到的页面&#xff0c;通常是整个网站最重要的一部分。首屏的设计和内容对于吸引用户的注意力、传达品牌形象和价值、促使用户继续浏览和进行交互非常关键。以下是官网首屏的重要性的几个方面&#xff1a; 1. 第一印象&#xff1a; 首屏是用…

Redis官方可视化管理工具

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl RedisInsight是一个Redis可视化工具&#xff0c;提供设计、开发和优化 Redis 应用程序的功能。RedisInsight分为免费的社区版和一个付费的企业版&#xff0c;免费版具有基本…

文心一言 VS 讯飞星火 VS chatgpt (297)-- 算法导论22.1 1题

一、给定有向图的邻接链表&#xff0c;需要多长时间才能计算出每个结点的出度(发出的边的条数)&#xff1f;多长时间才能计算出每个结点的入度(进入的边的条数)&#xff1f;如果要写代码&#xff0c;请用go语言。 文心一言&#xff1a; 计算出度 对于有向图的邻接链表表示&a…

C++ 引用——常量引用

作用&#xff1a;常量引用主要用来修饰形参&#xff0c;防止误操作 在函数形参列表中&#xff0c;可以加const修饰形参&#xff0c;防止形参改变实参 示例&#xff1a; 运行结果&#xff1a;

【Linux】进程优先级 + 环境变量

前言 在了解进程状态之后&#xff0c;本章我们将来学习一下进程优先级&#xff0c;还有环境变量等。。 目录 1.进程优先级1.1 为什么要有优先级&#xff1f; 2.进程的其他概念2.1 竞争性与独立性2.2 并行与并发2.3 进程间优先级的体现&#xff1a;2.3.1 O(1) 调度算法&#xf…

202406 CCF-GESP Python 四级试题及详细答案注释

202406 CCF-GESP Python 四级试题及详细答案注释 1 单选题(每题 2 分,共 30 分)第 1 题 小杨父母带他到某培训机构给他报名参加CCF组织的GESP认证考试的第1级,那他可以选择的认证语言有几种?( ) A. 1 B. 2 C. 3 D. 4答案:C解析:目前CCF组织的GESP认证考试有C++、Pyth…

Element中的表格组件Table和分页组件Pagination

简述&#xff1a;在 Element UI 中&#xff0c;Table组件是一个功能强大的数据展示工具&#xff0c;用于呈现结构化的数据列表。它提供了丰富的特性&#xff0c;使得数据展示不仅美观而且高效。而Pagination组件是一个用于实现数据分页显示的强大工具。它允许用户在大量数据中导…

【OJ】运行时错误(Runtime Error)导致递归爆栈问题

在进行OJ赛时&#xff0c; 题目&#xff1a;给你一个整数n&#xff0c;问最多能将其分解为多少质数的和。在第一行输出最多的质数数量k,下一行输出k个整数&#xff0c;为这些质数。 出现运行时错误 代码如下&#xff1a; def main():# code heren int(eval(input()))list …