我最近一直在研究改进我网站上的动画——更具体地说是移动设备上的导航下拉菜单。
在这方面,我偶然发现了以下案例,我希望对此有更深入的了解。
情况是在过渡/动画时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 速度降低)。
使用百分比转换:
使用像素 (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
以像素而不是百分比为单位的值。对于生产情况,这自然需要在调整窗口大小时进行更新。这种方法的最终时间表是:
$(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/