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 即可适配缩放
相关推荐
程序员agions7 分钟前
2026年,微前端终于“死“了
前端·状态模式
万岳科技系统开发7 分钟前
食堂采购系统源码库存扣减算法与并发控制实现详解
java·前端·数据库·算法
程序员猫哥_15 分钟前
HTML 生成网页工具推荐:从手写代码到 AI 自动生成网页的进化路径
前端·人工智能·html
龙飞0515 分钟前
Systemd -systemctl - journalctl 速查表:服务管理 + 日志排障
linux·运维·前端·chrome·systemctl·journalctl
我爱加班、、20 分钟前
Websocket能携带token过去后端吗
前端·后端·websocket
AAA阿giao21 分钟前
从零拆解一个 React + TypeScript 的 TodoList:模块化、数据流与工程实践
前端·react.js·ui·typescript·前端框架
杨超越luckly27 分钟前
HTML应用指南:利用GET请求获取中国500强企业名单,揭秘企业增长、分化与转型的新常态
前端·数据库·html·可视化·中国500强
愚者游世43 分钟前
Delegating Constructor(委托构造函数)各版本异同
开发语言·c++·程序人生·面试·改行学it
hedley(●'◡'●)1 小时前
基于cesium和vue的大疆司空模仿程序
前端·javascript·vue.js·python·typescript·无人机
qq5_8115175151 小时前
web城乡居民基本医疗信息管理系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】
前端·vue.js·spring boot