JavaScript放大镜效果

做一个小兔鲜儿项目的产品页面,可以点击四个小图片切换大图片,同时实现放大镜的效果,代码随便辅助粘贴,跟着一步步写起来吧!

业务分析: Demo

  1. 鼠标经过对应小盒子,左侧中等盒子显示对应中等图片
    • 获取对应的元素
    • 用事件委托监听鼠标经过小盒子里面的图片,用mouseover事件冒泡触发small
    • 让鼠标经过小图片的爸爸Ii盒子,添加类,其余的li移除类(注意先移除,后添加)
    • 鼠标经过小图片,可以拿到小图片的src,可以做两件事
    • 让中等盒子的图片换成这个这个小图片的src
    • 让大盒子的背景图片,也换成这个小图片的src(稍后做)
  2. 鼠标经过中盒子,右侧会显示放大镜效果的大盒子
    • 用到鼠标经过和离开,鼠标经过中盒子,大盒子利用display 来显示和隐藏
    • 鼠标离开不会立马消失,而是有200ms的延时,用户体验更好,所以尽量使用定时器做个延时
    • 显示和隐藏定义个函数,鼠标经过离开中盒子会显示隐藏,同时鼠标经过大盒子也会显示和隐藏
    • 给大盒子里面的背景图片一个默认的第一张图片
  3. 黑色遮罩盒子跟着鼠标来移动
    • 先做鼠标经过中等盒子,显示隐藏黑色遮罩的盒子
    • 让黑色遮罩跟着鼠标来走,需要用到鼠标移动事件mousemove
    • 黑色盒子移动:不断把鼠标在small盒子内的坐标给黑色遮罩层let top值,这样遮罩层就可以跟着移动了
    • 需求:
      • 我们要的是鼠标在中等盒子内的坐标,没有办法直接得到
      • 得到1:鼠标在页面中的坐标
      • 得到2:中等盒子在页面中的坐标
    • 算法:
      • 得到鼠标在页面中的坐标 利用事件对象的pagex
      • 得到middle中等盒子在页面中的坐标middle.getBoundingClientRect()
      • 鼠标在middle盒子中的坐标=鼠标在页面中的坐标-middle中等盒子的坐标
      • 黑色遮罩层不断得到 鼠标在middle盒子中的坐标就可以移动起来了
        • 为什么不用box.offsetLetbox.offsetTop因为这俩属性跟带有定位的父级有关系,很容被父级影响,而getBoundingClientRect()不受定位的父元素的影响
      • 限定遮罩的盒子只能在middle 内部移动,需要添加判断:
        • 限定水平方向 大于等于0并且小于等于400
        • 限定垂直方向 大于等于0并且小于等于400
      • 遮罩盒子移动的坐标:
        • 声明一个mx作为移动的距离
        • 水平坐标x如果小于等于100,则移动的距离mx就是。不应该移动
        • 水平坐标如果大于等于100并且小于300,移动的距离就是mx-100(100是遮罩盒子自身宽度的一半)
        • 水平坐标如果大于等于300,移动的距离就是mx200不应该在移动了
        • 其实我们发现水平移动,就在100~200之间移动的
        • 垂直同理
  4. 鼠标在中等盒子上移动,大盒子的图片跟着显示对应位置
    • 大盒子图片移动的计算方法:
      • 中等盒子是400px大盒子是800px的图片
      • 中等盒子移动1px,大盒子就应该移动2px,只不过是负值
// 1. 获取三个盒子,图片切换效果
const small = document.querySelector('.small')  // 小盒子
const middle = document.querySelector('.middle')// 中盒子
const large = document.querySelector('.large')  // 大盒子

// 1.1事件委托 冒泡事件侦听的是图片 
small.addEventListener('mouseover', function (e) {
  // 判断条件:鼠标经过图片
  if (e.target.tagName === 'IMG') {
    // console.log(11)
    // 排查思想 干掉以前的类
    this.querySelector('.active').classList.remove('active')
    // 当前元素的亲爸爸li添加 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})`
  }
})

// 2. 鼠标经过中盒子,右侧会显示放大镜效果的大盒子
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)
}

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

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

// 5. 移动黑色遮罩盒子 
middle.addEventListener('mousemove', function (e) {
  // 鼠标在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个变量 黑盒子移动的变量
    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'
  }
})

原创文章,作者:霍欣标,如若转载,请注明出处:https://www.bigengwu.cn/xue/143.html

霍欣标的头像霍欣标
上一篇 2024-08-26
下一篇 2024-09-06

相关推荐

博主人懒,应管局要求暂不开启站内私信和评论功能,如需帮助请发邮件。

邮箱账号:1969600480@qq.com