JS 打造「放大镜 + 缩略图」一体组件

电商详情页的经典三件套:缩略图列表 + 中等图展示 + 局部放大图。本文js原生代码实现一条无依赖、可复用、可扩展的放大镜链路,涵盖事件委托、边界计算、背景定位三大核心技能。

效果预览

一、HTML 骨架

html 复制代码
<div class="container">
  <!-- 中等图 -->
  <div class="left-img">
    <div class="mask"></div>
  </div>
  <!-- 放大图 -->
  <div class="right-img"></div>
  <!-- 缩略图列表 -->
  <ul class="img-list"></ul>
</div>
  • left-img:中等图,承担点击切换与鼠标探测双重职责
  • mask:绝对定位遮罩,用于局部高亮与边界计算
  • right-img:放大图,背景图定位实现局部放大效果

二、数据约定

js 复制代码
var imgs = {
  small: ['imgA_1.jpg', 'imgB_1.jpg', 'imgC_1.jpg'],
  middle: ['imgA_2.jpg', 'imgB_2.jpg', 'imgC_2.jpg'],
  large: ['imgA_3.jpg', 'imgB_3.jpg', 'imgC_3.jpg']
}
  • 三张图按索引一一对应,切换时只需同步 backgroundImage
  • 缩略图定宽定高,中等图与放大图定宽不定高,保持比例

三、JS链式事件三步走

1.初始化:渲染缩略图 + 默认激活

js 复制代码
function initPage() {
  let html = ''
  for (let i = 0; i < imgs.small.length; i++) {
    html += `<li style="background-image:url(./images/${imgs.small[i]});"></li>`
  }
  $('.img-list').innerHTML = html
  $('.img-list li').style.border = '2px solid #000'   // 默认选中第一张
}

2.点击缩略图:同步切换中等图与大图

js 复制代码
$('.img-list').onclick = function (e) {
  if (e.target.tagName !== 'LI') return
  // 让所有 LI 失活
  $$('li').forEach(li => li.style.border = 'none')
  // 让当前 LI 激活
  e.target.style.border = '2px solid #000'

  const index = [].indexOf.call(this.children, e.target)
  $('.left-img').style.backgroundImage = `url(./images/${imgs.middle[index]})`
  $('.right-img').style.backgroundImage = `url(./images/${imgs.large[index]})`
}

使用事件委托,缩略图数量随意增减,无需重新绑定。

3.鼠标移动:遮罩层跟随 + 大图定位

js 复制代码
$('.left-img').onmousemove = function (e) {
  const mask = $('.mask')
  const large = $('.right-img')
  mask.style.opacity = 1
  large.style.opacity = 1

  // 计算遮罩层中心坐标
  let left = e.clientX - this.offsetLeft - mask.offsetWidth / 2
  let top = e.clientY - this.offsetTop - mask.offsetHeight / 2

  // 边界条件:不让遮罩跑出中等图
  left = Math.max(0, Math.min(left, this.offsetWidth - mask.offsetWidth))
  top = Math.max(0, Math.min(top, this.offsetHeight - mask.offsetHeight))

  mask.style.left = left + 'px'
  mask.style.top = top + 'px'

  // 大图反向移动,实现局部放大
  large.style.backgroundPositionX = -left + 'px'
  large.style.backgroundPositionY = -top + 'px'
}

边界计算拆解

  • left ≤ 0 时强制归零
  • left ≥ (中等图宽 - 遮罩宽) 时强制贴边
  • 同理处理 top 高度方向

背景定位技巧

遮罩向右移动 10px,大图背景向左移动 10px,形成「窗口」效果;Y 轴同理。


四、鼠标离开:自动隐藏

js 复制代码
$('.left-img').onmouseleave = function () {
  $('.mask').style.opacity = 0
  $('.right-img').style.opacity = 0
}

只用 opacity 控制显隐,避免 display: none 触发重排;背景图已预加载,无闪烁。

性能 & 扩展

  • 零依赖:原生 DOM API,gzip < 1 KB
  • 零重排:仅用 opacitybackground-position,不改动布局
  • 可异步:把 initPage 换成 fetch 即可接入后端图片列表
  • 可响应:把 offsetWidth 换成 getBoundingClientRect 即可适配缩放
相关推荐
zimoyin2 分钟前
Stoplight Elements WebComponents 原生 WEB 组件化技术生成 Swagger优美界面
前端
Irene19916 分钟前
Python 面向对象总结:对比 JavaScript 的面向对象
javascript·python·面向对象
zhensherlock11 分钟前
Protocol Launcher 系列:Working Copy 提交与同步全攻略
javascript·git·typescript·node.js·自动化·github·js
天若有情67312 分钟前
【开源推荐】form-validator-cn 轻量级中文表单校验库 | TS 零依赖、极简开箱即用
前端·npm·开源·node·js·表单校验
one_love_zfl27 分钟前
java面试-spring篇
java·spring·面试
shjita29 分钟前
maven涉及的配置
java·前端·maven
兩尛33 分钟前
C++面向对象和类相关
java·c++·面试
changshuaihua00135 分钟前
useState 状态管理
开发语言·前端·javascript·react.js
帅次35 分钟前
Android 高级工程师面试参考答案:架构设计、Jetpack 与 Compose
android·面试·职场和发展·架构·composer·jetpack
鹏程十八少41 分钟前
6. 2026金三银四 面试官最爱的 Binder:一次拷贝、Activity 启动流程,这篇全搞定
前端·面试·前端框架