JavaScript Web API入门day7

目录

1.图片切换模块

2.鼠标经过以及离开中等盒子,大盒子的处理

3.黑色遮罩层的位置以及放大功能

4.放大镜的完整代码


1.图片切换模块

效果图:

思路分析:

①:鼠标经过小盒子,左侧中等盒子显示对应中等图片

  1. 获取对应的元素

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

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

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

    • 让中等盒子的图片换成这个 这个小图片的src

    • 让大盒子的背景图片,也换成这个小图片的 src (稍后做)

代码实现:

javascript 复制代码
<script>
        //1.获取对象
    const small = document.querySelector('.small')
    const middle = document.querySelector('.middle')
  
    //2.鼠标经过事件(因为用到事件委托,因此需要用到冒泡,用mouseover)
    small.addEventListener('mouseover', function (e) {
      // console.log(11)
      // 图片生效  
      if (e.target.tagName === 'IMG') {
        //排他思想   查找small下的active,并且移除
        this.querySelector('.active').classList.remove('active')
        //图片对象的父亲 也就是li ,添加active
        e.target.parentNode.classList.add('active')

        // 可以获取到图片地址
        // console.log(e.target.src)
        // 把图片地址赋值给中盒子的图片
        middle.querySelector('img').src = e.target.src
      }

    })
</script>

2.鼠标经过以及离开中等盒子,大盒子的处理

效果图:

思路分析:

②: 鼠标经过中等盒子,右侧大盒子显示

  1. 用到鼠标经过和离开,鼠标经过中盒子,大盒子 利用 display 来显示和隐藏

  2. 鼠标离开不会立马消失,而是有200ms的延时,用户体验更好,所以尽量使用定时器做个延时 setTimeout

  3. 显示和隐藏也尽量定义一个函数,因为鼠标经过离开中等盒子,会显示隐藏,同时,鼠标经过大盒子,也会显示和隐藏

  4. 给大盒子里面的背景图片一个默认的第一张图片

代码实现:

javascript 复制代码
<script>
    //1.获取对象
    const small = document.querySelector('.small')
    const middle = document.querySelector('.middle')
    const large = document.querySelector('.large')

    //2.鼠标经过事件(因为用到事件委托,因此需要用到冒泡,用mouseover)
    small.addEventListener('mouseover', function (e) {
      // console.log(11)
      // 图片生效  
      if (e.target.tagName === 'IMG') {
        //排他思想   查找small下的active,并且移除
        this.querySelector('.active').classList.remove('active')
        //图片对象的父亲 也就是li ,添加active
        e.target.parentNode.classList.add('active')

        // 可以获取到图片地址
        // console.log(e.target.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 timeout = 0
    //定义显示和隐藏函数
    function show() {
      //重置延时器(用户移动速度过快会出现bug)
      clearTimeout(timeout)
      large.style.display = 'block'
    }

    function hide() {
      //延迟器可以让用户体验更好
      timeout = 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'
    })

3.黑色遮罩层的位置以及放大功能

实现效果:

思路分析:

③: 黑色遮罩盒子跟着鼠标来移动

  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 之间移动的

      • 垂直同理

代码实现:

javascript 复制代码
<script>
    //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) {
      // console.log(11)
      // 鼠标距离左侧的位置
      // console.log(e.pageX)

      // 这里用getBoundingClientRect(),不用offset的原因是因为offset会受到定位的影响
      // console.log(this.getBoundingClientRect())

      // 得到黑色盒子相对于中等盒子的位置
      let x = e.pageX - this.getBoundingClientRect().left
      // 注意这里要减去被卷入的长度,不然遮罩会偏位,原因:滚动条滚动,this.getBoundingClientRect().top距离顶部变短
      let y = e.pageY - this.getBoundingClientRect().top - document.documentElement.scrollTop

      // 限定遮罩盒子在中等盒子内
      if (x >= 0 && x <= 400 && y >= 0 && y <= 400) {
        //鼠标动了,黑色盒子不一定要移动
        let mx = 0, my = 0
        // 让遮罩限定在中等盒子内
        if (x < 100) mx = 0
        // 这里减100是因为100以下的不变坐标
        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'

        // 放大镜效果(相反方向)
        large.style.backgroundPositionX = -2 * mx + 'px'
        large.style.backgroundPositionY = -2 * my + 'px'
      }

    })
</script>

4.放大镜的完整代码

代码:

javascript 复制代码
  <script>
    //1.获取对象
    const small = document.querySelector('.small')
    const middle = document.querySelector('.middle')
    const large = document.querySelector('.large')

    //2.鼠标经过事件(因为用到事件委托,因此需要用到冒泡,用mouseover)
    small.addEventListener('mouseover', function (e) {
      // console.log(11)
      // 图片生效  
      if (e.target.tagName === 'IMG') {
        //排他思想   查找small下的active,并且移除
        this.querySelector('.active').classList.remove('active')
        //图片对象的父亲 也就是li ,添加active
        e.target.parentNode.classList.add('active')

        // 可以获取到图片地址
        // console.log(e.target.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 timeout = 0
    //定义显示和隐藏函数
    function show() {
      //重置延时器(用户移动速度过快会出现bug)
      clearTimeout(timeout)
      large.style.display = 'block'
    }

    function hide() {
      //延迟器可以让用户体验更好
      timeout = 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) {
      // console.log(11)
      // 鼠标距离左侧的位置
      // console.log(e.pageX)

      // 这里用getBoundingClientRect(),不用offset的原因是因为offset会受到定位的影响
      // console.log(this.getBoundingClientRect())

      // 得到黑色盒子相对于中等盒子的位置
      let x = e.pageX - this.getBoundingClientRect().left
      // 注意这里要减去被卷入的长度,不然遮罩会偏位,原因:滚动条滚动,this.getBoundingClientRect().top距离顶部变短
      let y = e.pageY - this.getBoundingClientRect().top - document.documentElement.scrollTop

      // 限定遮罩盒子在中等盒子内
      if (x >= 0 && x <= 400 && y >= 0 && y <= 400) {
        //鼠标动了,黑色盒子不一定要移动
        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'

        // 放大镜效果(相反方向)
        large.style.backgroundPositionX = -2 * mx + 'px'
        large.style.backgroundPositionY = -2 * my + 'px'
      }

    })

  </script>
相关推荐
旭久几秒前
vue-计算两个日期之前的天数小方法
前端·javascript·vue.js
游王子4 分钟前
Vue.js组件(6):echarts组件
前端·vue.js·echarts
Smile_Gently31 分钟前
Ubuntu环境 nginx.conf详解(二)
运维·服务器·前端·nginx·ubuntu
m0_748233881 小时前
黑马程序员JavaWeb开发教程(前端部分) ---笔记分享
前端·笔记
温轻舟1 小时前
前端开发 -- 自定义鼠标指针样式
开发语言·前端·javascript·css·html·温轻舟
天天打码1 小时前
ThinkPHP项目如何关闭runtime下Log日志文件记录
android·java·javascript
冰镇屎壳郎2 小时前
前端安全 常见的攻击类型及防御措施
前端·安全·前端安全
2401_857617622 小时前
“无缝购物体验”:跨平台网上购物商城的设计与实现
java·开发语言·前端·安全·架构·php
2401_857439692 小时前
智慧社区电商系统:提升用户体验的界面设计
前端·javascript·php·ux
我是高手高手高高手2 小时前
ThinkPHP8多应用配置及不同域名访问不同应用的配置
linux·服务器·前端·php