mousemove触发缩略图切换的多实例冲突及CSS雪碧图适配问题
问题修复方案
问题1:多实例联动冲突修复
冲突原因
原代码所有DOM选择都是全局匹配,没有绑定到当前触发鼠标事件的单个缩略图组件,只要任意一个缩略图触发mousemove事件,就会修改页面所有匹配img标签的src属性,导致全量联动。
修复思路
所有DOM操作都限定在当前触发事件的缩略图组件父容器范围内,不做全局选择:
- 事件回调里用
$(this)获取当前鼠标悬停的.imageHolder元素 - 用
.closest('figure')找到当前元素所属的父级figure容器,只读取这个容器上绑定的图片列表数据 - 所有属性修改只针对当前的
.imageHolder元素,不影响其他实例
修复后完整代码
HTML结构可任意复制多份figure组件,无需额外改动,只要每个figure上的data-image-list填入自身对应的3张图地址即可:
<article> <!-- 缩略图组件1 --> <figure data-image-list="img1-1.png,img1-2.png,img1-3.png"> <img class="imageHolder" data-src="default1.png" src="default1.png" /> </figure> <!-- 缩略图组件2,可任意新增复制,不会出现联动冲突 --> <figure data-image-list="img2-1.png,img2-2.png,img2-3.png"> <img class="imageHolder" data-src="default2.png" src="default2.png" /> </figure> </article>
修复后的JS代码:
$(".imageHolder").mousemove(function (event) { // 锁定当前触发事件的图片元素,所有操作仅针对当前实例 const $currentImg = $(this); const xPos = event.pageX; const imgPos = $currentImg.offset().left; const imgWidth = $currentImg.width(); const change2 = imgPos + imgWidth / 3; const change3 = imgPos + 2 * imgWidth / 3; // 仅读取当前实例所属父容器的图片配置 const $currentFigure = $currentImg.closest('figure'); const imgList = $currentFigure.data("imageList").split(','); // 仅修改当前实例的显示内容 if (xPos > change3) { $currentImg.attr("src", imgList[2]); } else if (xPos > change2) { $currentImg.attr("src", imgList[1]); } else { $currentImg.attr("src", imgList[0]); } }); // 鼠标移出时仅重置当前实例 $(".imageHolder").mouseout(function () { $(this).attr("src", $(this).data("src")); });
注:这里把原代码的三个串行if判断改成了if else结构,避免每次鼠标移动都执行三次重复判断和赋值,运行性能更好。
问题2:CSS雪碧图适配方案
如果使用雪碧图,不需要切换img的src属性,只要给每个缩略图容器设置固定宽高,通过修改background-position显示雪碧图的不同区域即可,相比切换src的方案加载速度更快,也不会出现图片切换的短暂闪烁问题。
适配思路
- 把每个缩略图对应的3张图合并为单张三列雪碧图,每张子图尺寸和缩略图显示尺寸一致:比如缩略图显示宽度为200px,单张雪碧图总宽度为600px,高度和缩略图一致为200px
- 把原来的
img标签替换为块级容器(如div),给容器设置固定宽高,初始背景设置为默认占位状态 - 不需要再用
data-image-list存储多图地址,只要给每个容器存储雪碧图三个展示状态对应的background-position偏移值即可 - 鼠标移动时根据光标位置修改当前容器的
background-position属性
雪碧图版本代码示例
HTML结构:
<article> <!-- 缩略图组件1,data-positions存储三个状态的背景偏移值,格式:x偏移 y偏移 --> <figure> <div class="imageHolder" data-default-pos="0 0" data-positions="0 0,-200px 0,-400px 0" style="width:200px;height:200px;background:url(sprite1.png) no-repeat 0 0;"> </div> </figure> <!-- 缩略图组件2 --> <figure> <div class="imageHolder" data-default-pos="0 0" data-positions="0 0,-200px 0,-400px 0" style="width:200px;height:200px;background:url(sprite2.png) no-repeat 0 0;"> </div> </figure> </article>
对应JS代码:
$(".imageHolder").mousemove(function (event) { const $current = $(this); const xPos = event.pageX; const imgPos = $current.offset().left; const imgWidth = $current.width(); const change2 = imgPos + imgWidth / 3; const change3 = imgPos + 2 * imgWidth / 3; const posList = $current.data("positions").split(','); if (xPos > change3) { $current.css("background-position", posList[2]); } else if (xPos > change2) { $current.css("background-position", posList[1]); } else { $current.css("background-position", posList[0]); } }); $(".imageHolder").mouseout(function () { $(this).css("background-position", $(this).data("default-pos")); });
如果你的雪碧图是纵向排列的,只要把data-positions里的偏移值改为纵向偏移即可,交互逻辑不需要调整。
内容的提问来源于stack exchange,提问作者varldenn
相关产品推荐
相关产品推荐

