产品详情页鼠标移入图片的放大镜效果(HTML+CSS+JS)

275 阅读5分钟

2022-10-08 21-45-02_2.gif 以上是笔者实现效果转出的GIF图(图片质量压缩,清晰度损失)
用户可通过该效果直观的看到产品的细节质感

思路总结

1.分析结构:大致分为左右两个结构,左边鼠标移入盒子会出现一个半透明的遮罩层,跟随着鼠标移动且鼠标移出盒子后消失。在鼠标移入左边盒子后右边会出现一个大图,并且实时反馈鼠标在小盒子上的坐标位置所得的大图信息。

2.准备好所需要的素材

3.HTML部分:整个分为左右两个大区域左边product产品展示区域,右边text文本区域。 文本区域写上文字内容即可。左边product产品展示区域,分为左边preview_img实际产品图片区域,以及右边big展示放大图片区域。左边preview_img有两个部分图片和mask遮罩。

4.CSS部分:我使用less写法,设置好样式,mask和右边的大图用绝对定位。

5.JS部分:首先鼠标经过preview_img会显示和隐藏mask和big大图片盒子,分别给mouseover和mouseout鼠标监听事件。然后当鼠标在左边preview_img图片盒子上移动的时候,让mask遮罩跟着鼠标来走,所以需要判断和计算出mask的坐标,在mousemove鼠标监听事件中,分别需要计算出鼠标在盒子内的坐标,mask的Left和Top值,mask的最大移动宽高度,然后if-else判断出当鼠标移入才会出现mask,从而得到mask的最终移动坐标。最后需要计算出大图片的移动距离,先计算出大图片的最大移动距离,然后通过比例运算得到大图的移动坐标。

image.png

实际操作

  1. HTML部分
  <div class="box">
    <!-- @产品展示放大效果 -->
    <div class="product">
      <!-- ^左边实际产品区域 -->
      <div class="preview_img">
        <!-- 图片 -->
        <img src="./img/clothing.png" alt="">
        <!-- 遮罩 -->
        <div class="mask"></div>
      </div>
      <!-- ^右边展示放大区域 -->
      <div class="big">
        <!-- 放大的图片 -->
        <img src="./img/clothing-big.png" alt="" class="bigImg">
      </div>
    </div>
    <!-- @文字 -->
    <div class="text">
      <p class="tex1">
        汉服的简单介绍汉服,又称汉衣冠和华夏衣冠、汉装、华服,是汉族的传统民族服饰。汉服由2尺2寸宽的布料裁剪而成,分为领子、翻领、翻领、翻领、袖子、上衣、腰带、钹十个部分。取两块等长的布,对折,作为前面的后腰带,缝上后面的中缝。直领双排扣衣服是前面没有接缝的衣服。再拿一块布,剪成两条裤子,缝在左右翻领上,就是斜领的右裤了。前面后腰带的中缝叫腰带,也就是督脉和任脉,在任脉的右侧,所以叫右腰带。裾的长度分为腰、膝和足。根据长度,汉服有三种长度,即鞘、鞘和深被。袖子和翻领之间的缝叫翻领,袖口叫曲。
      </p>
      <p class="tex2">
        汉服,全称是“中国传统服饰”,也叫汉衣冠,中国服饰,中国服饰。它是从黄帝登基到17世纪中叶(明末清初),在汉族主要聚居区,以“华夏-汉”文化为背景和主导思想,以中国礼仪文化为中心,经过自然演变形成的具有独特中国风格和性格的传统服饰和配饰体系,与其他民族有着明显的不同。它承载着汉民族染、织、绣等优秀工艺和审美,传承着30多项中国非物质文化遗产和受保护的中国工艺美术,是中国“穿衣赴国”、“礼仪之邦”、“锦绣中华”和居鲁士国的体现。
      </p>
    </div>
  </div>
  1. CSS部分
.box {
  display: flex;
  margin: 50px 0 0 100px;
  // @产品展示放大效果
  .product {
    // ^左边实际产品区域
    .preview_img {
      position: relative;
      // 图片
      img {
        outline: 1px solid goldenrod;
        width: 300px;
      }
      // 遮罩
      .mask {
        display: none;
        position: absolute;
        top: 0;
        left: 0;
        width: 120px;
        height: 120px;
        background-color: pink;
        opacity: 0.3;
      }
    }
    // ^右边展示放大区域
    .big {
      display: none;
      position: absolute;
      top: 20px;
      left: 500px;
      width: 650px;
      height: 650px;
      border: 1px solid goldenrod;
      overflow: hidden;
      .bigImg {
        position: absolute;
        width: 800px;
        top: 0;
        left: 0;
      }
    }
  }
  // @文字
  .text {
    margin: 0 0 0 100px;
    width: 600px;
    p {
      font-size: 14px;
      text-indent: 2em;
      line-height: 23px;
    }
    .tex2 {
      margin-top: 20px;
    }
  }
}
  1. JS部分
window.onload = function () {
  let preview_img = document.querySelector('.preview_img')
  let mask = document.querySelector('.mask')
  let big = document.querySelector('.big')
  // #鼠标经过preview_img显示和隐藏mask遮挡层和big大盒子
  // 显示
  preview_img.addEventListener('mouseover', function () {
    mask.style.display = 'block'
    big.style.display = 'block'
  })
  // 隐藏
  preview_img.addEventListener('mouseout', function () {
    mask.style.display = 'none'
    big.style.display = 'none'
  })
  // #鼠标在图片盒子上移动的时候,让黄色的盒子跟着鼠标来走
  // e(event)事件对象
  preview_img.addEventListener('mousemove', function (e) {
    // 计算鼠标在图片盒子上的坐标
    // @用鼠标距离页面的坐标 - 盒子在页面中的距离 = 鼠标在盒子内的坐标
    let x = e.pageX - this.offsetLeft
    let y = e.pageY - this.offsetTop
    // 计算mask的Left和Top值
    // @鼠标在盒子内的坐标 - mask高度和宽度的一半 = mask的Left和Top值
    let maskLeft = x - mask.offsetWidth / 2
    let maskTop = y - mask.offsetHeight / 2

    // 计算mask的最大移动宽度和高度
    // @图片盒子的宽高度- mask的宽高度 = mask的最大移动宽高度
    let maskMaxmoveWidth = preview_img.offsetWidth - mask.offsetWidth
    let maskMaxmoveHeight = preview_img.offsetHeight - mask.offsetHeight

    // 超出盒子上下左右区域的 if判断
    // @如果mask的Left值小于等于0,那么就是0
    if (maskLeft <= 0) {
      maskLeft = 0
      // @如果mask的Left值大于mask的最大移动宽度,那么就是mask的最大移动宽度
    } else if (maskLeft >= maskMaxmoveWidth) {
      maskLeft = maskMaxmoveWidth
    }
    if (maskTop <= 0) {
      maskTop = 0
    } else if (maskTop >= maskMaxmoveHeight) {
      maskTop = maskMaxmoveHeight
    }
    // mask的移动坐标
    mask.style.left = maskLeft + 'px'
    mask.style.top = maskTop + 'px'
    // 打印一下鼠标的坐标
    console.log(x, y)

    // 获取大图
    let bigIMg = document.querySelector('.bigImg')
    let big = document.querySelector('.big')
    // 大图片最大移动距离
    // @大图片的宽度 - 盒子容器的宽度 = 大图片的最大移动距离
    let bigMax = bigIMg.offsetWidth - big.offsetWidth
    // 大图片的移动距离 X Y
    // @比例运算
    let bigX = (maskLeft * bigMax) / maskMaxmoveWidth
    let bigY = (maskTop * bigMax) / maskMaxmoveHeight
    bigIMg.style.left = -bigX + 'px'
    bigIMg.style.top = -bigY + 'px'
  })
}

关于素材

素材来源于站酷成都的三维服装设计师觉非Kay20000的作品:汉服-冷香丸-虚拟模特-溪羽
使用ZB数字雕刻人物模型,MD制作角色布料,贴图是SubstanceDesigner和SubstancePainter制作的,最后导入Blender里渲染。我觉得这位艺术家做的布料质感很好,放大后也有不错的细节,所以借这位大佬的作品用一下。 汉服-冷香丸-虚拟模特-溪羽.jpg 汉服-冷香丸-虚拟模特-溪羽.jpg