JavaScript应用(day07:实战案例)

学习源码可以看我的个人前端学习笔记 (github.com):qdxzw/frontlearningNotes

觉得有帮助的同学,可以点心心支持一下哈

放大镜效果

JavaScript应用(day07:实战案例)_第1张图片

业务分析

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

  1. 获取对应的元素
  2. 采取事件委托的形式,监听鼠标经过小盒子里面的图片, 注意此时需要使用 mouseover 事件,因为需要事件冒泡触发small
  3. 让鼠标经过小图片的爸爸li盒子,添加类,其余的li移除类(注意先移除,后添加)
  4. 鼠标经过小图片,可以拿到小图片的src, 可以做两件事
    • 让中等盒子的图片换成这个 这个小图片的src
    • 让大盒子的背景图片,也换成这个小图片的 src (稍后做)
      // ①:鼠标经过对应小盒子,左侧中等盒子显示对应中等图片
      const small = document.querySelector('.small')
      const middleImg = document.querySelector('.middle img')
      const largeImg = document.querySelector('.large')
      // 通过事件委托对图片进行绑定事件
      small.addEventListener('mouseover', function (e) {
        if (e.target.tagName === 'IMG') {
          // 排他
          this.querySelector('.active').classList.remove('active')
          // 给li(img的父元素)添加类名
          e.target.parentNode.classList.add('active')
          // 将小盒子的路径给中等盒子
          middleImg.src = e.target.src
          // 将小盒子的路径给大盒子
          largeImg.style.backgroundImage = `url(${e.target.src})`
        }
      })

②: 鼠标经过中盒子,右侧会显示放大镜效果的大盒子

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

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

  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 之间移动的
      • 垂直同理

④: 鼠标在中等盒子上移动,大盒子的图片跟着显示对应位置

大盒子图片移动的计算方法:

- 中等盒子是 400px 大盒子 是 800px 的图片

- 中等盒子移动1px, 大盒子就应该移动2px, 只不过是负值

  // ③: 黑色遮罩盒子跟着鼠标来移动
      const layer = document.querySelector('.layer')
      middleImg.addEventListener('mouseenter', function () {
        // 鼠标进入显示黑色遮罩盒子
        layer.style.display = 'block'
      })
      middleImg.addEventListener('mouseleave', function () {
        // 鼠标移出隐藏黑色遮罩盒子
        layer.style.display = 'none'
      })
      middleImg.addEventListener('mousemove', function (e) {
        // pageX得到鼠标在页面中的坐标
        // console.log(e.pageX)
        // 得到middle中等盒子在页面中的坐标 middle.getBoundingClientRect()
        // console.log(middleImg.getBoundingClientRect().x)
        // 鼠标在middle 盒子里面的坐标 = 鼠标在页面中的坐标 - middle 中等盒子的坐标
        let middleMouseX = e.pageX - middleImg.getBoundingClientRect().x
        // 注意 y坐标特殊,需要减去 页面被卷去的头部
        let middleMouseY =
          e.pageY -
          middleImg.getBoundingClientRect().y -
          document.documentElement.scrollTop
        // 遮罩的盒子移动
        // 限定垂直方向 大于等于0 并且小于等于 400
        //  限定水平方向 大于等于0 并且小于等于 400
        if (
          middleMouseY >= 0 &&
          middleMouseY <= 400 &&
          middleMouseX >= 0 &&
          middleMouseX <= 400
        ) {
          // 遮罩盒子移动的坐标:
          // ■ 声明一个 mx 作为移动的距离
          // ■ 水平坐标 x 如果 小于等于100 ,则移动的距离 mx 就是 0 不应该移动
          // ■ 水平坐标 如果 大于等于100 并且小于300,移动的距离就是 mx - 100 (100是遮罩盒子自身宽度的一半)
          // ■ 水平坐标 如果 大于等于300,移动的距离就是 mx 就是200 不应该在移动了
          // ■ 其实我们发现水平移动, 就在 100 ~ 200 之间移动的
          // ■ 垂直同理
          let mx = 0
          // 水平坐标 如果 大于等于300,移动的距离就是 mx 就是200 不应该在移动了
          if (middleMouseX >= 300) {
            mx = 200
          } else if (middleMouseX >= 100) {
            // 水平坐标 如果 大于等于100 并且小于300,移动的距离就是 mx - 100
            mx = middleMouseX - 100
          } else {
            mx = 0
          }
          let my = 0
          // 垂直坐标 如果 大于等于300,移动的距离就是 my 就是200 不应该在移动了
          if (middleMouseY >= 300) {
            my = 200
          } else if (middleMouseY >= 100) {
            // 垂直坐标 如果 大于等于100 并且小于300,移动的距离就是 my - 100
            my = middleMouseY - 100
          } else {
            my = 0
          }
          layer.style.top = my + 'px'
          layer.style.left = mx + 'px'
          // ④: 鼠标在中等盒子上移动,大盒子的图片跟着显示对应位置
          // - 中等盒子是 400px  大盒子 是 800px 的图片
          // - 中等盒子移动1px, 大盒子就应该移动2px, 只不过是负值
          largeImg.style.backgroundPositionX = -2 * mx + 'px'
          largeImg.style.backgroundPositionY = -2 * my + 'px'
        }
      })

完整代码

// ①:鼠标经过对应小盒子,左侧中等盒子显示对应中等图片
const small = document.querySelector('.small')
const middleImg = document.querySelector('.middle')
const largeImg = document.querySelector('.large')
// 通过事件委托对图片进行绑定事件
small.addEventListener('mouseover', function (e) {
  if (e.target.tagName === 'IMG') {
    // 排他
    this.querySelector('.active').classList.remove('active')
    // 给li(img的父元素)添加类名
    e.target.parentNode.classList.add('active')
    // 将小盒子的路径给中等盒子
    middleImg.querySelector('img').src = e.target.src
    // 将小盒子的路径给大盒子
    largeImg.style.backgroundImage = `url(${e.target.src})`
  }
})

// ②: 鼠标经过中盒子,右侧会显示放大镜效果的大盒子
// 定义显示和隐藏函数
let timeId = null
function show() {
  clearTimeout(timeId)
  largeImg.style.display = 'block'
}
function hidde() {
  timeId = setTimeout(function () {
    largeImg.style.display = 'none'
  }, 200)
}
middleImg.addEventListener('mouseover', show)
middleImg.addEventListener('mouseleave', hidde)
largeImg.addEventListener('mouseover', show)
largeImg.addEventListener('mouseleave', hidde)
// ③: 黑色遮罩盒子跟着鼠标来移动
const layer = document.querySelector('.layer')
middleImg.addEventListener('mouseenter', function () {
  // 鼠标进入显示黑色遮罩盒子
  layer.style.display = 'block'
})
middleImg.addEventListener('mouseleave', function () {
  // 鼠标移出隐藏黑色遮罩盒子
  layer.style.display = 'none'
})
middleImg.addEventListener('mousemove', function (e) {
  // pageX得到鼠标在页面中的坐标
  // console.log(e.pageX)
  // 得到middle中等盒子在页面中的坐标 middle.getBoundingClientRect()
  // console.log(middleImg.getBoundingClientRect().x)
  // 鼠标在middle 盒子里面的坐标 = 鼠标在页面中的坐标 - middle 中等盒子的坐标
  let middleMouseX = e.pageX - middleImg.getBoundingClientRect().x
  // 注意 y坐标特殊,需要减去 页面被卷去的头部
  let middleMouseY =
    e.pageY -
    middleImg.getBoundingClientRect().y -
    document.documentElement.scrollTop
  // 遮罩的盒子移动
  // 限定垂直方向 大于等于0 并且小于等于 400
  //  限定水平方向 大于等于0 并且小于等于 400
  if (
    middleMouseY >= 0 &&
    middleMouseY <= 400 &&
    middleMouseX >= 0 &&
    middleMouseX <= 400
  ) {
    // 遮罩盒子移动的坐标:
    // ■ 声明一个 mx 作为移动的距离
    // ■ 水平坐标 x 如果 小于等于100 ,则移动的距离 mx 就是 0 不应该移动
    // ■ 水平坐标 如果 大于等于100 并且小于300,移动的距离就是 mx - 100 (100是遮罩盒子自身宽度的一半)
    // ■ 水平坐标 如果 大于等于300,移动的距离就是 mx 就是200 不应该在移动了
    // ■ 其实我们发现水平移动, 就在 100 ~ 200 之间移动的
    // ■ 垂直同理
    let mx = 0
    // 水平坐标 如果 大于等于300,移动的距离就是 mx 就是200 不应该在移动了
    if (middleMouseX >= 300) {
      mx = 200
    } else if (middleMouseX >= 100) {
      // 水平坐标 如果 大于等于100 并且小于300,移动的距离就是 mx - 100
      mx = middleMouseX - 100
    } else {
      mx = 0
    }
    let my = 0
      // 垂直坐标 如果 大于等于300,移动的距离就是 my 就是200 不应该在移动了
          if (middleMouseY >= 300) {
            my = 200
          } else if (middleMouseY >= 100) {
            // 垂直坐标 如果 大于等于100 并且小于300,移动的距离就是 my - 100
            my = middleMouseY - 100
          } else {
            my = 0
          }
          layer.style.top = my + 'px'
          layer.style.left = mx + 'px'
          // ④: 鼠标在中等盒子上移动,大盒子的图片跟着显示对应位置
          // - 中等盒子是 400px  大盒子 是 800px 的图片
          // - 中等盒子移动1px, 大盒子就应该移动2px, 只不过是负值
          largeImg.style.backgroundPositionX = -2 * mx + 'px'
          largeImg.style.backgroundPositionY = -2 * my + 'px'
        }
      })

你可能感兴趣的:(JavaScript应用,javascript,前端)