jquery - CSS 转换过渡 - 使用“px”比 'percentage' 更平滑/性能更好

标签 jquery css css-transitions css-animations css-transforms

我最近一直在研究改进我网站上的动画——更具体地说是移动设备上的导航下拉菜单。

在这方面,我偶然发现了以下案例,我希望对此有更深入的了解。

情况是在过渡/动画时transform: translate3d()似乎浏览器在使用 % 应用时需要更多的计算而不是 px .例如。在我的测试中,似乎从 transform: translate3d(0, 500px, 0) 过渡至 transform: translate3d(0,0,0)与从 transform: translate3d(0, 100%, 0) 过渡相比,需要更少的计算并且运行更流畅.

更新:经过进一步测试,我发现使用 100vh/100vw绕过/减轻使用百分比的问题。这在元素具有已知百分比宽度的窗口或全宽的情况下很有用,从而提高性能。实际上,似乎使用这个值的行为就像是用 px 分配的一样。 Chrome 中的值。

这是每个动画的时间线的几张图片。时间线是使用谷歌开发工具在“性能”下获得的。为了更好地显示差异,Chrome Dev Tools 中的性能被限制为“低端移动”(6 倍 CPU 速度降低)。

使用百分比转换:

Transform performance using percent (%)

使用像素 (px) 进行变换:

Transform performance using pixel (px)

从图像中可以看出,使用 % 时似乎进行了更多的渲染和绘画。而不是 px来确定转换。浏览器必须计算每一帧的百分比值(我猜?),这是很有意义的,但我很惊讶,与使用像素值相比,它需要更多。

还有请注意,显示百分比时间线的图片中的帧率从未达到约 60 fps,而是平均约为 40 fps。

以下是复制案例的片段。有一种使用百分比,一种使用 px。

$(document).on("click", function(){
$(".bb").toggleClass("active");
});
.aa{
  height:50px;
  background:blue;
  position:fixed;
  top:0;
  width:100%;

}
.bb{
  position:fixed;
  top:0px;
  background:none;
  height:100%;
  width:100%;
  left:0;
  transform:translateZ(0);
  overflow:hidden;
    pointer-events:none;
}
.cc{
  height:100%;
    transform:translate3d(0,500px,0);
    width:100%;
      transition:transform .5s ease-in;
      background:red;
}
.bb.active .cc{
  transform:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Click the document to start animation<p>
<div class="bb">
<div class="cc">
<ul>
<li>Point one</li>
<li>Point two</li>
<li>Point three</li>
<li>Point four</li>
<li>Point five</li>
<li>Point six</li>
<li>Point seven</li>
</ul><ul>
<li>Point one</li>
<li>Point two</li>
<li>Point three</li>
<li>Point four</li>
<li>Point five</li>
<li>Point six</li>
<li>Point seven</li>
</ul>

</div>

</div>



$(document).on("click", function(){
$(".bb").toggleClass("active");
});
.aa{
  height:50px;
  background:blue;
  position:fixed;
  top:0;
  width:100%;

}
.bb{
  position:fixed;
  top:0px;
  background:none;
  height:100%;
  width:100%;
  left:0;
  transform:translateZ(0);
  overflow:hidden;
    pointer-events:none;
}
.cc{
  height:100%;
    transform:translate3d(0,100%,0);
    width:100%;
      transition:transform .5s ease-in;
      background:red;
}
.bb.active .cc{
  transform:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Click the document to start animation<p>
<div class="bb">
<div class="cc">
<ul>
<li>Point one</li>
<li>Point two</li>
<li>Point three</li>
<li>Point four</li>
<li>Point five</li>
<li>Point six</li>
<li>Point seven</li>
</ul><ul>
<li>Point one</li>
<li>Point two</li>
<li>Point three</li>
<li>Point four</li>
<li>Point five</li>
<li>Point six</li>
<li>Point seven</li>
</ul>

</div>

</div>


解决这个“问题”,即在 transform 中使用百分比可能会导致动画性能变差,我提出了以下建议,这可能会提高性能。但是,我有兴趣听取其他意见,因为我不太确定这是否必要以及为什么(?)。

我正在做的基本上只是使用 jQuery 来应用 transform以像素而不是百分比为单位的值。对于生产情况,这自然需要在调整窗口大小时进行更新。

这种方法的最终时间表是:

enter image description here

$(document).ready(function(){
var bbWidth = $("#bb .cc").css('transform').split(',')[5].slice(0,-1);

$("#bb .cc").css("transform", "translate3d(0," + bbWidth + "px,0");
$(document).on("click", function(){
$("#bb").toggleClass("active");
});
});
.aa{
  height:50px;
  background:blue;
  position:fixed;
  top:0;
  width:100%;

}
#bb{
  position:fixed;
  top:0px;
  background:none;
  height:100%;
  width:100%;
  left:0;
  transform:translateZ(0);
  overflow:hidden;
}
.cc{
  height:100%;
    transform:translate3d(0,100%,0);
    width:100%;
      transition:transform .5s ease-in;
      background:red;
      position:absolute;
      top:0;
}
#bb.active .cc{
  transform:none!important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="bb">
<div class="cc">
<ul>
<li>Point one</li>
<li>Point two</li>
<li>Point three</li>
<li>Point four</li>
<li>Point five</li>
<li>Point six</li>
<li>Point seven</li>
</ul><ul>
<li>Point one</li>
<li>Point two</li>
<li>Point three</li>
<li>Point four</li>
<li>Point five</li>
<li>Point six</li>
<li>Point seven</li>
</ul>

</div>

</div>


问题:
  • 我遇到这种行为是否正确(在 px 中赋值比 % 表现更好),如果是这样,为什么会发生这种情况?正如前面提到的,它应该对我来说有点道理,但我真的缺乏一些技术/深入的解释。
  • 有没有比我的建议更好的绕过这个问题的方法?使用 transform: translate()例如如果您“不能”使用 %,在屏幕外隐藏导航是非常重要的如果您同时想要流畅的动画。
  • 最佳答案

    Is it correct that I'm experiencing this behaviour (assigning value in px performs better than %) and if so, why is this happening? As mentioned earlier it kinda makes sense to me that it should, but I'm really lacking some technological/in-depth explanation.



    确实是对的。像素是绝对值(即不依赖于任何东西并“按原样”表示)。百分比是相对值,这意味着它们必须依赖于其他一些值才能产生结果。因此,每次分配百分比值时,它都必须获得它的相对值才能执行计算。
    使用像素进行平移时,您只需更改平移值,但使用百分比时,您必须先获取元素的尺寸,然后再应用平移。并且必须对每个动画帧都这样做。

    为了缓解这个问题,你只需要在动画之前重新计算元素的尺寸一次。然后使用 !important覆盖样式属性中设置的内容。片段中的代码正是这样做的。

    另请注意,我添加了 resize听众。如果窗口被调整大小,这是必需的,因此您的元素将被隐藏。

    $(function(){
    var $el = $("#bb");
    $(document).on("click", function(){
      var height = $el.outerHeight();
      $el
        .css('transform', 'translateY(' + height + 'px)')
        .toggleClass("active");
    });
    $(window).on('resize', function() {
      $el.removeClass('active').removeAttr('style');
    });
    });
    #bb{
      position:fixed;
      top:0px;
      background-color: red;
      height:100%;
      width:100%;
      left:0;
      overflow:hidden;
      transform: translateY(100%);
      transition: transform .5s ease-in;
    }
    #bb.active
    {
      transform: translateY(0px) !important;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div id="bb">
    <div class="cc">
    <ul>
    <li>Point one</li>
    <li>Point two</li>
    <li>Point three</li>
    <li>Point four</li>
    <li>Point five</li>
    <li>Point six</li>
    <li>Point seven</li>
    </ul><ul>
    <li>Point one</li>
    <li>Point two</li>
    <li>Point three</li>
    <li>Point four</li>
    <li>Point five</li>
    <li>Point six</li>
    <li>Point seven</li>
    </ul>
    
    </div>
    
    </div>

    关于jquery - CSS 转换过渡 - 使用“px”比 'percentage' 更平滑/性能更好,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50409008/

    相关文章:

    javascript - 显示带有书签的隐藏 div

    javascript - 动态表单操作 URL

    javascript - 总是通过滚动一个非常大的数字来滚动到一个可滚动的 div 到底部

    jquery - html 5 网站在 chrome 和 firefox 中给出不同的结果

    css - 如何使文本在div内滑动

    jQuery AJAX 访问 REST API JSON 数据

    jquery - pdf加载到iframe时如何防止下载?

    css - 垂直滚动条不出现

    html - CSS淡入,即时隐藏

    javascript - 等待CSS过渡