CSS过渡在不同浏览器中表现不同的问题

11

在我的代码中,我根据当前鼠标的X和Y位置更改某些元素的位置。我添加了CSS transition: all 5000ms;以使动画更加平滑。

在Google Chrome(版本63)中看起来很棒,而在Internet ExplorerFirefox中,动画看起来卡顿/不流畅。

这是我的代码:

// $('.shape').css("transition", "all 7000ms");
$(document).mousemove(function(e){
    let mX = e.clientX;
    let mY = e.clientY;
    $('.shape-1').css("transform", "translate("+mX/10+"px, "+mY/10+"px)");
});

有没有人知道为什么浏览器对CSS过渡的处理方式不同?

没有CSS过渡的JSFiddle示例:https://jsfiddle.net/2rrcp27L/9/

有CSS过渡的JSFiddle示例:https://jsfiddle.net/2rrcp27L/6/


3
加入未来,放弃支持Internet Explorer,专注于使用Edge。 - Tschallacka
@Tschallacka 但在Firefox中效果也非常卡顿... - sol
1
为什么不使用 transition: transform 500ms 而不是 all - kumarharsh
@kumar 我可以这样做,但这仍然不能解决Firefox的问题:https://jsfiddle.net/2rrcp27L/11/ - JiiB
4个回答

10
这种情况发生的主要原因是 mouseMove 事件触发非常频繁,Chrome 可以处理但 Firefox 可能无法处理,而 IE 绝对无法优化这种情况。您应该对处理程序的调用进行节流,可以参考 Lodash文档。请查看此示例:https://jsfiddle.net/s2f9d77x/。另外,建议您指定 transition: transform 而不是 transition: all,以告诉浏览器不用担心元素的其他属性。

你可以尝试不同的油门超时值,看哪个对你的情况最有效。 - kumarharsh
1
此外,作为最佳实践,也许不要在最终网站中包含整个lodash包,而只需包含lodash.throttle子包 - 如果可能的话。 - kumarharsh
尽管我不喜欢为这样一个简单的任务包含lodash(在我看来),但它似乎是最好的解决方案。谢谢@kumar - JiiB
如果你愿意的话,你可以自己编写节流函数。我只是用lodash来说明这一点。此外,你可以在你的项目中只使用lodash/throttle - 不需要全部引入。 - kumarharsh
是的,我刚刚做到了,可以查看下面我的答案。再次感谢@kumar_harsh。 - JiiB

8
问题似乎在于鼠标事件的频率 - 在转换效果完成之前设置新的转换。FF/IE 似乎会将值重置为上一个完成的转换,而 Chrome 则从当前动画状态开始。解决方案可能是将 left 和 translate 属性组合设置,就像更新后的代码片段中一样,通过更新 left/top 属性来“模拟”转换的结束。这仍然有点跳跃,因为每次鼠标移动都会即时更新到先前的鼠标事件,但不会那么跳跃。如果您想更好地控制动画,则必须编写远比现在更复杂的 JavaScript 代码。

$('.shape')
   .css("transition", "transform 200ms cubic-bezier(0, 1.17, 1, 1)")
   .each(function() {
     $(this).data("left", parseInt($(this).css("left")));
     $(this).data("top", parseInt($(this).css("top")));
   });
 let factors = [
   [10, 10],
   [3, 3],
   [5, 5],
   [7, 7]
 ];
 let mX, mY;
 $(window).on('mousemove', function(e) {

   if (typeof mX !== "undefined") {
     $('.shape').each(function(idx) {
       let $shape = $(this);
       $shape.css({
         "left": $shape.data("left") + mX / factors[idx][0],
         "top": $shape.data("top") + mY / factors[idx][1],
         "transform": "translate(" + (e.clientX - mX) / factors[idx][0] + "px, " + (e.clientY - mY) / factors[idx][1] + "px)"
       });
     })
   }

   mX = e.clientX;
   mY = e.clientY;


 });
body {
    background: #E1F7E7;
    background: -moz-linear-gradient(45deg, rgba(169,232,220,1) 0%, rgba(225,247,231,1) 50%, rgba(169,232,220,1) 100%); /* ff3.6+ */
    background: -webkit-gradient(linear, left bottom, right top, color-stop(0%, rgba(169,232,220,1)), color-stop(50%, rgba(225,247,231,1)), color-stop(100%, rgba(169,232,220,1))); /* safari4+,chrome */
    background: -webkit-linear-gradient(45deg, rgba(169,232,220,1) 0%, rgba(225,247,231,1) 50%, rgba(169,232,220,1) 100%); /* safari5.1+,chrome10+ */
    background: -o-linear-gradient(45deg, rgba(169,232,220,1) 0%, rgba(225,247,231,1) 50%, rgba(169,232,220,1) 100%); /* opera 11.10+ */
    background: -ms-linear-gradient(45deg, rgba(169,232,220,1) 0%, rgba(225,247,231,1) 50%, rgba(169,232,220,1) 100%); /* ie10+ */
    background: linear-gradient(45deg, rgba(169,232,220,1) 0%, rgba(225,247,231,1) 50%, rgba(169,232,220,1) 100%); /* w3c */
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#a9e8dc', endColorstr='#a9e8dc',GradientType=1 ); /* ie6-9 */
}
.shape {
    position: fixed;
    transform-origin: center;
}
.shape:after{
    position: absolute;
    content: "";
    left: -25px;
    top: -50px;
    border-left: 50px solid transparent;
    border-right: 50px solid transparent;
    border-bottom: 500px solid;
}

.shape-1 {
    top: 50px;
    left: 200px;
}
.shape.shape-1:after {
    transform: rotate(190deg);
    border-bottom-color: #A9E8DC;
}

.shape-2 {
    bottom: 300px;
    left: 250px;
}
.shape.shape-2:after {
    transform: rotate(19deg);
    border-bottom-color: #02BEC4;
}
.shape-3 {
    
    bottom: 380px;
    right: 220px;
}
.shape.shape-3:after {
    transform: rotate(-19deg);
    border-bottom-color: #0284A8;
}

.shape-4 {
    top: 200px;
    right: 180px;
}
.shape.shape-4:after {
    transform: rotate(-190deg);
    border-bottom-color: #050C42;
}

@media (max-width: 1450px) {
    .shape.shape-4:after {
        transform: rotate(-190deg);
        border-bottom-color: #02BEC4;
    }
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.slim.min.js"></script>
<div class="shape shape-1"></div>
<div class="shape shape-2"></div>
<div class="shape shape-3"></div>
<div class="shape shape-4"></div>
<div class="container">
  <h1>Hello World</h1>
  <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsum magnam unde earum voluptas quae? Molestiae cum suscipit, esse placeat eligendi rerum nam minus inventore. Voluptatum impedit sunt quisquam officiis eius obcaecati totam aliquid incidunt
    vel aliquam. Nemo quae iusto perferendis corrupti provident sint quisquam, impedit nesciunt architecto a, ea necessitatibus!</p>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ratione, eveniet! Harum saepe quia inventore, atque dolorem culpa debitis. Blanditiis ad ab delectus, magnam assumenda sequi corrupti dolorum incidunt eligendi obcaecati magni! Veniam maxime
    ratione placeat veritatis excepturi. Nisi sed, dolorum, maxime laboriosam magnam vel aperiam beatae autem dicta, totam commodi? Modi, ratione tempore recusandae nulla suscipit quaerat earum repudiandae vero sit ad dolorem quasi, laboriosam culpa.
    Sequi, laboriosam assumenda? Aliquid esse impedit cum reprehenderit ex ipsa deleniti nam pariatur alias iusto sit tempore tempora eius optio voluptates veniam, laboriosam aliquam, odio corporis possimus nihil fugiat. Consectetur repellendus fugit
    dolorum ipsa ullam optio tempora maxime possimus, atque aut doloribus, iusto quam? Repellendus ipsa, praesentium tempore incidunt quasi cumque quidem nostrum harum non facilis doloremque voluptates quis architecto consequuntur consequatur. Illo, eius?
    Dolorem deserunt ipsam error voluptates necessitatibus iste dolor? Quo adipisci corporis incidunt fuga sapiente recusandae qui quod, impedit maiores! Eum blanditiis natus officiis inventore architecto! Aliquid quis praesentium doloremque laboriosam
    consectetur veniam excepturi inventore, exercitationem iusto sed, maxime sunt laudantium porro possimus esse? Dolor eveniet laborum aut tempore blanditiis voluptatem asperiores dolore incidunt, ipsa ea ut consequatur, itaque sint reprehenderit aliquam
    nesciunt debitis ex quia. Cupiditate beatae sapiente minima, fuga architecto, ad, aliquam provident et corporis tempore nostrum natus labore hic in eaque dolor perspiciatis nesciunt deleniti error unde. Sapiente nemo deleniti omnis quod odit accusamus
    obcaecati ea culpa ut fugiat, cumque vitae? Iste corporis quo illum nesciunt fugit quis officia consequuntur sit eum dignissimos. Necessitatibus autem eligendi quod quis tenetur, quos excepturi rerum repudiandae ullam magnam sequi consequuntur voluptate
    sint nemo ea, at tempora. Dolore consequuntur excepturi perferendis cumque tempore nam consequatur sit tempora cupiditate nisi magnam quos nulla nobis iste optio voluptas temporibus mollitia quibusdam hic, eaque vitae culpa dolorum error? Beatae numquam
    animi distinctio doloribus unde velit quasi quisquam necessitatibus reprehenderit vitae, obcaecati minus, tempora illo impedit ullam blanditiis vero excepturi ratione fugiat nemo? Quidem dicta perspiciatis iste cum, quisquam vel minima consequuntur
    blanditiis aperiam, sequi eligendi exercitationem inventore, eos facilis laborum beatae excepturi praesentium dolore quaerat assumenda quo obcaecati? Dolores, pariatur suscipit! Voluptate inventore assumenda delectus optio totam adipisci amet distinctio
    exercitationem sint debitis ea, vel deleniti odio odit. Illo adipisci, id, dolores culpa voluptatum eligendi fugit numquam quis accusamus possimus, ea odit laborum ullam non quasi! Dicta est aliquid saepe! In officia, dolor quo architecto illum repudiandae.
    Suscipit, pariatur sed commodi quod dolorem beatae quae!</p>
  <h2>What up?</h2>
  <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Itaque, dolor quam. Fugiat numquam eius animi omnis explicabo atque. Expedita velit unde iure earum, sit id esse provident odit illum recusandae deserunt laborum quis molestiae omnis! Laborum
    ea officiis exercitationem perferendis magnam temporibus eligendi porro earum nobis nesciunt. Ducimus quisquam commodi eum, pariatur, illo sint doloribus similique ea fuga porro sapiente, quam blanditiis. Veritatis quasi officia soluta explicabo nobis!
    Explicabo id voluptate quasi tenetur iste eum dolor illo, architecto, harum ad cum provident vero, saepe unde sed? Doloribus eaque pariatur sequi officia. Sit ipsam doloribus molestias ipsum adipisci recusandae explicabo sint ad rem magni, ducimus
    eligendi! Velit, dolore illo laboriosam ipsa, a sunt eum soluta nesciunt expedita porro atque maiores dolores amet temporibus nemo, cum hic libero autem ad? Nobis molestiae accusantium dolor aspernatur dolorem exercitationem reprehenderit quisquam
    est, fuga distinctio neque, iste, libero necessitatibus. Voluptatum aut ducimus autem magnam, quaerat iusto rem libero iste magni odio voluptatibus excepturi voluptates ab dolor laudantium nesciunt, ea, enim totam? Nostrum unde enim accusamus aliquid
    debitis sint amet commodi, iusto maxime distinctio. Nobis aut quae molestiae et architecto quo animi aliquam, vel iste, expedita, nihil praesentium voluptates soluta sed? Illum natus, aspernatur iure expedita beatae maxime eveniet perferendis laborum
    recusandae quo temporibus voluptate dolores fugiat at. Sit aperiam minus et nemo doloremque nihil, alias libero dolor dolorum commodi pariatur in atque deleniti distinctio recusandae molestias consequuntur consectetur sapiente ut cupiditate fugiat
    eveniet. Ad quo quaerat consequuntur recusandae excepturi debitis tempora temporibus atque amet iure.</p>
  <br>
  <h2>and Good Bye...</h2>
  <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Cum unde, necessitatibus laboriosam obcaecati cumque eum iure blanditiis voluptate temporibus possimus quam suscipit dolore dicta reprehenderit repellendus? Minima, voluptate voluptatum! Nostrum
    modi minus dignissimos, minima omnis eligendi adipisci eaque consectetur totam incidunt vitae reprehenderit, corrupti qui dicta soluta nihil! In quasi porro temporibus ipsum similique, aspernatur velit ullam laudantium id molestiae ut esse provident
    natus, eius iste earum ab corrupti, officiis distinctio eos repellat tenetur odio. Temporibus, eum! Aliquid libero doloribus necessitatibus consequuntur adipisci dicta ducimus quam qui odit atque eius voluptates repellendus illo non perferendis eum
    reiciendis dolor aliquam, excepturi voluptatum. Temporibus veritatis autem, numquam ab maiores cumque exercitationem. Porro minima quod magni blanditiis cupiditate dolorum dolores qui, ipsum voluptas nostrum, soluta modi nam harum atque aliquid ea
    totam accusantium consectetur quae? Libero ad at atque quisquam enim accusamus, perferendis provident sequi, blanditiis velit recusandae odio tenetur deserunt quo incidunt quam eaque perspiciatis fugit in unde non quidem, natus labore? Eveniet ducimus
    eius ullam! Aut aperiam enim, voluptatibus, harum cumque voluptas debitis voluptatem ullam placeat omnis et magni dolorem asperiores obcaecati quo deleniti delectus error incidunt possimus expedita maiores quisquam reiciendis? Unde, reprehenderit.
    Et natus ullam asperiores sapiente veniam sint.</p>
</div>


谢谢你的回答,但是@kumar的版本对我来说效果最好。 - JiiB

2

过了一段时间,我找到了最适合我的解决方案,它不需要任何额外的库(除了jQuery)。

我基本上创建了自己的“节流”函数,只更新鼠标的当前x和y位置。

每次鼠标在浏览器窗口中移动时,我将鼠标位置附加到窗口对象上:

$(document).mousemove(function(e){
    var event = e || window.event;
    window.mouseX = event.clientX;
    window.mouseY = event.clientY;
});

我还有另一个函数,用于设置元素的位置:

function moveElements() {
   $('.shape-1').css("transform", "translate("+ window.mouseX/10 +"px, "+ window.mouseY/10 +"px)");
}

最后,moveElements()函数每100毫秒被调用一次,使用了setInterval()函数:

setInterval(moveElements, 100);

感谢@kumar_harsh给了我解决问题的思路。
我在以下浏览器中测试了此代码,并且没有任何卡顿或抖动:
- Chrome 63 - Firefox 57 - Internet Explorer 11 - Microsoft Edge 16 - Safari 11
这是我的最终JSFiddle链接:https://jsfiddle.net/2rrcp27L/27/

你有在任何地方取消 setInterval 吗?如果没有,那么即使用户不与页面交互,它仍将不断调用自身 - 消耗电池和资源。 - kumarharsh
我想向您推荐这篇文章,以更好地理解节流的概念,以及为什么使用它比仅使用 setInterval 更好:https://medium.com/@_jh3y/throttling-and-debouncing-in-javascript-b01cad5c8edf - kumarharsh

0

您可以使用:

-webkit-transform /* android, safari, chrome */

-moz-transform /* old firefox */

-o-transform /* old opera */

-ms-transform /* old IE */

transform   /*standard */

嗨@Mahmoud D. Alghraibeh,感谢您的回答。但我已经尝试过了,在火狐浏览器中仍然很卡顿。如果我没记错的话,火狐浏览器不需要使用-moz-前缀来进行转换:https://caniuse.com/#feat=css-transitions - JiiB
为了验证,除了IE之外,浏览器多年来或多个版本都不需要供应商前缀,这不可能是解决方案。 - Rob
我建议不要手动编写这样的代码。你应该使用autoprefixer来为你完成 - 这样可以减少维护成本,而且当那些浏览器变得太老而无法使用时,你也不必担心删除IE和Opera回退。例如,今天只有0.05%的人使用Opera 12.1 - 你真的需要为此编写代码吗? - kumarharsh
此外,我认为这并不会对Firefox/IE的性能有任何改善。这是一个渲染问题,而不是CSS兼容性问题。 - kumarharsh
1
@Rob:“当然,除了IE”,在任何稳定版本中都从未需要转换前缀,而唯一需要转换前缀的版本本身就不支持转换。 - BoltClock
@BoltClock 我在谈论变换时没有查阅资料,但这并不意味着厂商前缀在这里是必要的。 - Rob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接