如何解决鼠标触发的图片动画在Firefox浏览器中运行卡顿的问题
问题描述
实现了鼠标操作触发的图片动画效果,功能基本开发完成,但在Firefox浏览器中动画运行非常卡顿。相关代码如下:
JavaScript 代码
jQuery(document).ready(function($) { $('.box_effect').hover(function(e) { $(document).on("click mousemove", ".box_effect", function(e) { var x = e.clientX; var y = e.clientY; if ($(this).hasClass("right")) { console.log($(this)); var middleX1 = (x - $("#page").width() * 0.69) / 6; console.log('right'); } else if ($(this).hasClass("left")) { console.log('left'); var middleX1 = (x - $("#page").width() * 0.31) / 6; } var middleY1 = (y - $(window).height() * 0.4) / 8; var middleX2 = -middleX1 / 2; var middleY2 = (-middleY1) / 2; var image11 = $(this).find("img"); image11.css({ "-webkit-transform": "translate3d(" + middleX1 + "px," + middleY1 + "px,0px)", "-moz-transform": "translate3d(" + middleX1 + "px," + middleY1 + "px,0px)", "-ms-transform": "translate3d(" + middleX1 + "px," + middleY1 + "px,0px)", "-o-transform": "translate3d(" + middleX1 + "px," + middleY1 + "px,0px)", "transform": "translate3d(" + middleX1 + "px," + middleY1 + "px,0px)" }); var image12 = $(this).find(".border"); image12.css({ "-webkit-transform": "translate3d(" + middleX2 + "px," + middleY2 + "px,0px)", "-moz-transform": "translate3d(" + middleX2 + "px," + middleY2 + "px,0px)", "-ms-transform": "translate3d(" + middleX2 + "px," + middleY2 + "px,0px)", "-o-transform": "translate3d(" + middleX2 + "px," + middleY2 + "px,0px)", "transform": "translate3d(" + middleX2 + "px," + middleY2 + "px,0px)" }); }); }, function() { var image11 = $(this).find("img"); var image12 = $(this).find(".border"); image11.css({ "-webkit-transform": "translate3d(" + 0 + "px," + 0 + "px,0px)", "-moz-transform": "translate3d(" + 0 + "px," + 0 + "px,0px)", "-ms-transform": "translate3d(" + 0 + "px," + 0 + "px,0px)", "-o-transform": "translate3d(" + 0 + "px," + 0 + "px,0px)", "transform": "translate3d(" + 0 + "px," + 0 + "px,0px)" }); image12.css({ "-webkit-transform": "translate3d(" + 0 + "px," + 0 + "px,0px)", "-moz-transform": "translate3d(" + 0 + "px," + 0 + "px,0px)", "-ms-transform": "translate3d(" + 0 + "px," + 0 + "px,0px)", "-o-transform": "translate3d(" + 0 + "px," + 0 + "px,0px)", "transform": "translate3d(" + 0 + "px," + 0 + "px,0px)" }); } ); });
CSS 代码
body { margin: 0; display: block; } div { display: block; } .container { width: 75.3%; margin: auto; } .row { display: flex; justify-content: flex-end; } .row>div { width: 50%; padding: 6.484vw 3.984vw 4vw; } .box_effect { padding: 0 3.984vw; max-width: 450px; margin: auto; margin-bottom: 4vw; } .img_effect { position: relative; overflow: visible; margin-top: 2.187vw; z-index: -1; } .box_effect span.border { content: ""; display: block; position: absolute; left: 1.093vw; top: -2.0832vw; width: 86.84%; height: 97.87%; border: 3px solid #91b508; box-sizing: border-box; z-index: 3; max-width: 380px; } .box_effect img { max-width: 380px; width: 100%; } .box_effect .img_effect img, .box_effect .img_effect span { -webkit-transition: transform 5s cubic-bezier(0, 0.92, 0, 0.72)s; -moz-transition: transform 5s cubic-bezier(0, 0.92, 0, 0.72)s; -ms-transition: transform 5s cubic-bezier(0, 0.92, 0, 0.72)s; -o-transition: transform 5s cubic-bezier(0, 0.92, 0, 0.72)s; transition: transform 5s cubic-bezier(0, 0.92, 0, 0.72); -webkit-transform: translate3d(0px, 0px, 0px); -moz-transform: translate3d(0px, 0px, 0px); -o-transform: translate3d(0px, 0px, 0px); transform: translate3d(0px, 0px, 0px); }
HTML 代码
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <body> <div id="page" class="site"> <div class="container"> <div class="row one"> <div class="text"></div> <div class="right box_effect"> <div class="img_effect"> <span class="border" style="transform: translate3d(0px, 0px, 0px);"></span> <img src="占位图片地址" alt=""> </div> </div> </div> </div> </div> <!-- #page --> </body>
修复方案
导致Firefox卡顿的核心原因及对应修复方案如下:
- 修复重复事件绑定问题:原代码每次hover进入元素时都会给document新增一次
click和mousemove事件监听,多次hover后会积累成百上千个重复监听器,高频触发的mousemove事件直接占满主线程。修改逻辑为hover进入时绑定事件,离开时移除对应事件,避免事件重复绑定。 - 修复CSS语法错误:带前缀的
transition属性末尾多写了多余的s单位,错误的CSS语法导致Firefox渲染引擎解析过渡规则异常,拉低动画性能。删除所有带前缀transition属性末尾多余的s即可。 - 删除高频console.log输出:Firefox对控制台高频输出的性能处理弱于Chrome,mousemove每次触发都打印日志会占用大量计算资源,生产环境移除所有调试用的console.log语句。
- 新增GPU加速配置:给动画元素加上
will-change: transform属性,提前告知浏览器该元素会执行变换动画,浏览器会提前分配GPU资源处理渲染,大幅提升动画流畅度。
修复后核心代码
修复后JS代码
jQuery(document).ready(function($) { // 定义事件处理函数,方便后续解绑 function handleMove(e) { const $target = $(e.currentTarget); const x = e.clientX; const y = e.clientY; let middleX1; if ($target.hasClass("right")) { middleX1 = (x - $("#page").width() * 0.69) / 6; } else if ($target.hasClass("left")) { middleX1 = (x - $("#page").width() * 0.31) / 6; } const middleY1 = (y - $(window).height() * 0.4) / 8; const middleX2 = -middleX1 / 2; const middleY2 = -middleY1 / 2; const $img = $target.find("img"); const $border = $target.find(".border"); // 现代浏览器无需加transform前缀,减少冗余代码 $img.css("transform", `translate3d(${middleX1}px, ${middleY1}px, 0px)`); $border.css("transform", `translate3d(${middleX2}px, ${middleY2}px, 0px)`); } $('.box_effect').hover(function() { // hover进入时绑定事件 $(document).on("mousemove", ".box_effect", handleMove); }, function() { // hover离开时解绑事件,同时重置位置 $(document).off("mousemove", ".box_effect", handleMove); const $img = $(this).find("img"); const $border = $(this).find(".border"); $img.css("transform", "translate3d(0px, 0px, 0px)"); $border.css("transform", "translate3d(0px, 0px, 0px)"); }); });
修复后CSS代码(仅修改动画相关部分)
.box_effect .img_effect img, .box_effect .img_effect span { /* 移除多余的s,新增will-change属性触发GPU加速 */ -webkit-transition: transform 5s cubic-bezier(0, 0.92, 0, 0.72); -moz-transition: transform 5s cubic-bezier(0, 0.92, 0, 0.72); -ms-transition: transform 5s cubic-bezier(0, 0.92, 0, 0.72); -o-transition: transform 5s cubic-bezier(0, 0.92, 0, 0.72); transition: transform 5s cubic-bezier(0, 0.92, 0, 0.72); will-change: transform; transform: translate3d(0px, 0px, 0px); }
内容的提问来源于stack exchange,提问作者popcorn
相关产品推荐
相关产品推荐

