优化jQuery代码避免图片点击切换时淡入淡出动画重复执行
问题修复方案
动画重复触发的根本原因
- 多元素动画回调重复执行:你选择了多个元素绑定
fadeOut事件,jQuery会为每个完成淡出动画的元素单独执行一次回调函数,导致替换元素属性、包裹链接的逻辑被重复执行多次,额外绑定了重复的点击事件 - 旧事件未清理:仅修改元素ID不会移除之前绑定的点击事件,原
#shi的点击事件始终保留在DOM元素上,触发时会和新ID绑定的事件叠加执行 - 未做动画队列拦截:动画执行过程中没有锁机制,重复点击会导致动画队列堆叠,出现多次淡入淡出
修复方案
1. 核心逻辑优化点
- 使用
fadeOut().promise().done()替代直接传回调函数,保证所有元素动画完成后仅执行一次逻辑 - 每次绑定点击事件前先调用
.off('click')清理旧事件,避免事件叠加 - 增加动画锁变量,动画执行过程中阻止点击事件触发
- 用状态栈存储每一步的页面配置,点击返回时直接恢复上一级状态即可实现回退功能
2. 完整代码示例
HTML部分(新增返回按钮结构)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <!-- 新增返回按钮 --> <button id="backBtn" style="display:none; margin: 10px 0 0 20px;">返回上一级</button> <h1 id="ihi" class="ihc" style="color: #000000; font-family: Segoe, 'Segoe UI', 'DejaVu Sans', 'Trebuchet MS', Verdana, sans-serif; font-style: normal; font-weight: bold; text-align: center; font-size: 1.5em;"> Select the brand. </h1> <hr> <section class="isc" id="isi"> <div class="grc" id="gri"> <div class="gic" id="gsh"><img src="images/2021_images/Logos/SHI-SHC.svg" id="shi" class="shc" alt="S UK support" width="300" height="50"></div> <!--Row 1, column 1--> <div class="gic" id="gbp"><img src="images/2021_images/Logos/BPI-BPC.svg" id="bpi" class="bpc" alt="B support" width="300" height="50"></div> <!--Row 1, column 2--> <div class="gic" id="gth"><img src="images/2021_images/Logos/THI-THC.svg" id="thi" class="thc" alt="T support" width="300" height="50"></div> <!--Row 1, column 3--> <div class="gic" id="gem"><img src="images/2021_images/Logos/EMI-EMC.svg" id="emi" class="emc" alt="e support" width="300" height="50"></div> <!--Row 2, column 1--> <div class="gic" id="get"><img src="images/2021_images/Logos/ETI-ETC.svg" id="eti" class="etc" alt="E support" width="300" height="50"></div> <!--Row 2, column 2--> <div class="gic" id="gjm"><img src="images/2021_images/Logos/JMI-JMC.svg" id="jmi" class="jmc" alt="J support" width="300" height="50"></div> <!--Row 2, column 3--> <div class="gic" id="gbl3"><img src="images/2021_images/Logos/BLI-BLC.svg" id="bl3" class="blc" alt="blank 3" width="300" height="50"></div> <!--Row 3, column 1--> <div class="gic" id="gbl4"><img src="images/2021_images/Logos/BLI-BLC.svg" id="bl4" class="blc" alt="blank 4" width="300" height="50"></div> <!--Row 3, column 2--> <div class="gic" id="gbl5"><img src="images/2021_images/Logos/BLI-BLC.svg" id="bl5" class="blc" alt="blank 5" width="300" height="50"></div> <!--Row 3, column 3--> </div> </section>
JS部分
$(function() { // 动画锁,避免动画执行过程中重复触发 let isAnimating = false; // 状态栈,存储每一步的页面配置用于返回 let stateStack = []; // 存储初始状态 saveState(); // 初始页隐藏返回按钮 $('#backBtn').hide(); var idlist = $("#shi,#bpi,#thi,#emi,#eti,#jmi,#bl4,#ihi,#umi,#bl3,#bl5"); $("#shi").off('click').on('click', function() { if (isAnimating) return; isAnimating = true; // 操作前保存当前状态 saveState(); $(idlist).fadeOut(300).promise().done(function() { $("#gri").css("grid-gap", "160px 120px"); // 先解绑旧事件再修改属性 $("#shi").off('click').attr('src', "images/2021_images/Products/TVs/STVI-STVC.jpg").attr('id', "stvi").attr("height", "150").attr("alt", "STV Icon") $("#bpi").attr('src', "images/2021_images/Products/Audio/SAVI-SAVC.jpg").attr('id', "savi").attr("height", "150").attr("alt", "S link").wrap("<a href='https://www.goingsomeplace.com'>") $("#thi").attr('src', "images/2021_images/Products/Audio/SPKI-SPKC.jpg").attr('id', "spki").attr("height", "150").attr("alt", "S link2").wrap("<a href='https://www.goingsomeplace.com'>") $("#emi").attr('src', "images/2021_images/Products/Audio/SHFI-SHFC.jpg").attr('id', "shfi").attr("height", "150").attr("alt", "SHI link").wrap("<a href='https://www.goingsomeplace.com'>") $("#eti").attr('src', "images/2021_images/Products/Audio/SRAI-SRAC.jpg").attr('id', "srai").attr("height", "150").attr("alt", "SAR link").wrap("<a href='https://www.goingsomeplace.com'>") $("#jmi").attr('src', "images/2021_images/Products/SDA/SAPI-SAPC.jpg").attr('id', "sapi").attr("height", "150").attr("alt", "SAP link").wrap("<a href='https://www.goingsomeplace.com'>") $("#bl3").attr('src', "images/2021_images/Logos/BLI-BLC.svg").attr('id', "bl1").attr("alt", "Blank 1") $("#bl4").attr('src', "images/2021_images/Products/SDA/SMWI-SMWC.jpg").attr("id", "smwi").attr("height", "150").attr("alt", "SMW").wrap("<a href='https://www.goingsomeplace.com'>") $("#bl5").attr('src', "images/2021_images/Logos/BLI-BLC.svg").attr('id', "bl1").attr("alt", "Blank 1") $("#ihi").text("Which Sharp product do you need help with?").attr('id', "ihis") $("#umi").attr('src', "images/2021_images/Logos/SHI-SHC.svg").attr('id', "#shih") $(idlist).fadeIn(500, function() { isAnimating = false; // 操作后显示返回按钮 $('#backBtn').show(); }); }) }); //第二阶段点击事件 $(document).off('click', '#stvi').on('click', '#stvi', function() { if (isAnimating) return; isAnimating = true; saveState(); $("#stvi,#savi,#spki,#shfi,#srai,#sapi,#smwc,#ihis").fadeOut(300).promise().done(function() { $("#gri").css("grid-gap", "100px 100px") $("#stvi").off('click').attr('src', "images/2021_images/Logos/IMI-QSC.svg").attr("id", "imi").attr("alt", "S Support").wrap("<a href='https://www.goingsomeplace.com'>") $("#savi").attr('src', "images/2021_images/Logos/IMI-QSC.svg").attr("id", "faq").attr("alt", "S FAQ").wrap("<a href='https://www.goingsomeplace.com'>") $("#spki").attr('src', "images/2021_images/Logos/IMI-QSC.svg").attr("id", "faa").attr("alt", "S A.FAQ").wrap("<a href='https://www.goingsomeplace.com'>") $("#shfi").attr('src', "images/2021_images/Logos/BLI-BLC.svg").attr("id", "bl1").attr("alt", "Blank 1").unwrap(["#shfi"]) $("#srai").attr('src', "images/2021_images/Logos/BLI-BLC.svg").attr("id", "bl1").attr("alt", "Blank 1").unwrap(["#srai"]) $("#sapi").attr('src', "images/2021_images/Logos/BLI-BLC.svg").attr("id", "bl1").attr("alt", "Blank 1").unwrap(["#sapi"]) $("#smwi").attr('src', "images/2021_images/Logos/BLI-BLC.svg").attr("id", "bl1").attr("alt", "Blank 1").unwrap(["#smwi"]) $("#ihis").text("Support - S") $("#umi").attr('src', "images/2021_images/Logos/BPI-BPC.svg").attr("id", "#bpih") $(this).fadeIn(300, function() { isAnimating = false; }); }) }) // 返回按钮逻辑 $('#backBtn').on('click', function() { if (isAnimating || stateStack.length <=1) return; isAnimating = true; // 弹出当前状态,恢复上一级状态 stateStack.pop(); let prevState = stateStack[stateStack.length -1]; restoreState(prevState); // 回到初始页时隐藏返回按钮 if (stateStack.length ===1) { $('#backBtn').hide(); } }) // 保存当前页面状态到栈 function saveState() { let state = { gridGap: $('#gri').css('grid-gap'), title: $('#ihi, #ihis').text(), elements: [] }; $('#gri img').each(function() { let $el = $(this); state.elements.push({ parent: $el.parent().attr('id'), id: $el.attr('id'), src: $el.attr('src'), alt: $el.attr('alt'), height: $el.attr('height'), hasLink: $el.parent().is('a') }) }) stateStack.push(state); } // 恢复到指定状态 function restoreState(state) { let $imgs = $('#gri img'); $('#gri').css('grid-gap', state.gridGap); $('#ihi, #ihis').attr('id', 'ihi').text(state.title); $imgs.each(function(index) { let item = state.elements[index]; let $el = $(this); // 处理外层链接 if (item.hasLink && !$el.parent().is('a')) { $el.wrap("<a href='https://www.goingsomeplace.com'>"); } else if (!item.hasLink && $el.parent().is('a')) { $el.unwrap(); } // 恢复元素属性,先清旧事件 $el.off('click').attr({ id: item.id, src: item.src, alt: item.alt, height: item.height }) }) $imgs.fadeIn(300, function() { isAnimating = false; }) } })
CSS部分(可选新增返回按钮样式)
#backBtn { padding: 6px 12px; background: #02AB9D; color: #fff; border: none; border-radius: 4px; cursor: pointer; } .shic { width: 100%; background-color: #424750; padding-top: 0.5%; padding-bottom: 0.1%; } .shtc { font-size: 15px; font-family: 'Segoe UI'; color: #FFFFFF; margin-left: 20%; } /*BRANDS*/ .isi { margin-bottom: 2%; } #gri { display: grid; grid-template-columns: repeat(3, 100px); /* 3 columns */ grid-template-rows: repeat(3, 60px); /* 2 rows */ grid-gap: 100px 100px; /* 50 pixels of space added between rows and 100 pixels added between columns */ justify-content: center; margin-top: 1%; border-bottom: #02AB9D; border-bottom-width: 2px; } .gic { width: 300; height: 50; justify-content: bottom; }
内容的提问来源于stack exchange,提问作者D Sand
相关产品推荐
相关产品推荐

