同步的、昂贵的 CSS 转换可以同相吗?
Can simultaneous, expensive CSS transitions be in phase?
有关于 the absolute timing precision of CSS transitions and about removing jitter for inexpensive simultaneous transitions 的问题。但是,答案并没有让我清楚地了解动画计时的 相对 准确性(例如,如果两个同步动画是 "in-phase"),尤其是当过渡变得昂贵时.
处理图像时效果最为明显,例如 this fiddle,其中图像和容器同时沿相反方向移动,试图将图像保持在相同的绝对位置,但异步导致抖动:
/* CSS */
#container {
position:absolute;
width:200px;
height:200px;
left:200px;
overflow:hidden;
background-position:-200px -150px;
-webkit-backface-visiblity:hidden;
-webkit-transition:all 2s ease-in-out;
-moz-transition:all 2s ease-in-out;
-o-transition:all 2s ease-in-out;
transition:all 2s ease-in-out;
}
/* JS */
$(function() {
$('#container').css('left', 0).css('background-position', '0 -150px');
});
奇怪的是,抖动始终在中性的右侧,这意味着图像动画阶段比容器的动画阶段早一点。有点难看,但将偏移帧与静止的最终帧进行比较,方向偏差是可见的。
有什么方法可以确保同时呈现两个过渡的每个步骤?
我认为您看到的是 Jank.
它的发生是因为您试图为 CSS 属性设置动画。这两个 CSS 属性即 left
& background-position
触发 paint & compositing 操作。此外,left
属性 也会触发 layout。
阅读 High Performance Animations and also take a look at which CSS properties trigger which operation over at CSS Triggers 的主题。
作为解决方案,您可能需要 animate translateX
instead of left
属性。结果会好一点,但我们仍然需要 background-position
来处理这会不断触发重绘的繁重操作。
我认为最好的解决方案是在 #container
元素中添加一个 img
标签,并提供图像作为其 src
并从 CSS.
中删除所有 background
相关属性
然后使用上面提到的相同 translate
移动它。希望通过这种方式,您将获得最流畅的结果。
看看 this updated fiddle 或下面的代码片段。
片段:
$(document).ready(function() {
$('#container').css({
'-webkit-transform': 'translateX(0)',
'-moz-transform': 'translateX(0)',
'-o-transform': 'translateX(0)',
'transform': 'translateX(0)'
});
$('#container > img').css({
'-webkit-transform': 'translate(0px, -150px)',
'-moz-transform': 'translate(0px, -150px)',
'-o-transform': 'translate(0px, -150px)',
'transform': 'translate(0px, -150px)'
});
});
#container {
position: absolute;
width: 200px;
height: 200px;
left: 0px;
overflow: hidden;
-webkit-transform: translateX(200px);
-moz-transform: translateX(200px);
-o-transform: translateX(200px);
transform: translateX(200px);
-webkit-transition: all 2s ease-in-out;
-moz-transition: all 2s ease-in-out;
-o-transition: all 2s ease-in-out;
transition: all 2s ease-in-out;
}
#container > img {
-webkit-transform: translate(-200px, -150px);
-moz-transform: translate(-200px, -150px);
-o-transform: translate(-200px, -150px);
transform: translate(-200px, -150px);
-webkit-transition: all 2s ease-in-out;
-moz-transition: all 2s ease-in-out;
-o-transition: all 2s ease-in-out;
transition: all 2s ease-in-out;
}
body,
html {
margin: 0;
width: 100%;
height: 100%;
}
span {
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<span id="container">
<img src="https://images.unsplash.com/photo-1448975750337-b0290d621d6d?crop=entropy&dpr=2&fit=crop&fm=jpg&h=775&ixjsv=2.1.0&ixlib=rb-0.3.5&q=50&w=1450" />
</span>
P.S。作为旁注,我是 GSAP (a JavaScript animation suite of tools). Here is another example using TweenMax
(one of the tools from GSAP) which animates x
property (a shorthand for translateX
within the GSAP world and which also takes care of all the browser prefixes for you behind the scenes) in a more intuitive way using .fromTo()
方法的忠实粉丝。
有关于 the absolute timing precision of CSS transitions and about removing jitter for inexpensive simultaneous transitions 的问题。但是,答案并没有让我清楚地了解动画计时的 相对 准确性(例如,如果两个同步动画是 "in-phase"),尤其是当过渡变得昂贵时.
处理图像时效果最为明显,例如 this fiddle,其中图像和容器同时沿相反方向移动,试图将图像保持在相同的绝对位置,但异步导致抖动:
/* CSS */
#container {
position:absolute;
width:200px;
height:200px;
left:200px;
overflow:hidden;
background-position:-200px -150px;
-webkit-backface-visiblity:hidden;
-webkit-transition:all 2s ease-in-out;
-moz-transition:all 2s ease-in-out;
-o-transition:all 2s ease-in-out;
transition:all 2s ease-in-out;
}
/* JS */
$(function() {
$('#container').css('left', 0).css('background-position', '0 -150px');
});
奇怪的是,抖动始终在中性的右侧,这意味着图像动画阶段比容器的动画阶段早一点。有点难看,但将偏移帧与静止的最终帧进行比较,方向偏差是可见的。
有什么方法可以确保同时呈现两个过渡的每个步骤?
我认为您看到的是 Jank.
它的发生是因为您试图为 CSS 属性设置动画。这两个 CSS 属性即 left
& background-position
触发 paint & compositing 操作。此外,left
属性 也会触发 layout。
阅读 High Performance Animations and also take a look at which CSS properties trigger which operation over at CSS Triggers 的主题。
作为解决方案,您可能需要 animate translateX
instead of left
属性。结果会好一点,但我们仍然需要 background-position
来处理这会不断触发重绘的繁重操作。
我认为最好的解决方案是在 #container
元素中添加一个 img
标签,并提供图像作为其 src
并从 CSS.
background
相关属性
然后使用上面提到的相同 translate
移动它。希望通过这种方式,您将获得最流畅的结果。
看看 this updated fiddle 或下面的代码片段。
片段:
$(document).ready(function() {
$('#container').css({
'-webkit-transform': 'translateX(0)',
'-moz-transform': 'translateX(0)',
'-o-transform': 'translateX(0)',
'transform': 'translateX(0)'
});
$('#container > img').css({
'-webkit-transform': 'translate(0px, -150px)',
'-moz-transform': 'translate(0px, -150px)',
'-o-transform': 'translate(0px, -150px)',
'transform': 'translate(0px, -150px)'
});
});
#container {
position: absolute;
width: 200px;
height: 200px;
left: 0px;
overflow: hidden;
-webkit-transform: translateX(200px);
-moz-transform: translateX(200px);
-o-transform: translateX(200px);
transform: translateX(200px);
-webkit-transition: all 2s ease-in-out;
-moz-transition: all 2s ease-in-out;
-o-transition: all 2s ease-in-out;
transition: all 2s ease-in-out;
}
#container > img {
-webkit-transform: translate(-200px, -150px);
-moz-transform: translate(-200px, -150px);
-o-transform: translate(-200px, -150px);
transform: translate(-200px, -150px);
-webkit-transition: all 2s ease-in-out;
-moz-transition: all 2s ease-in-out;
-o-transition: all 2s ease-in-out;
transition: all 2s ease-in-out;
}
body,
html {
margin: 0;
width: 100%;
height: 100%;
}
span {
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<span id="container">
<img src="https://images.unsplash.com/photo-1448975750337-b0290d621d6d?crop=entropy&dpr=2&fit=crop&fm=jpg&h=775&ixjsv=2.1.0&ixlib=rb-0.3.5&q=50&w=1450" />
</span>
P.S。作为旁注,我是 GSAP (a JavaScript animation suite of tools). Here is another example using TweenMax
(one of the tools from GSAP) which animates x
property (a shorthand for translateX
within the GSAP world and which also takes care of all the browser prefixes for you behind the scenes) in a more intuitive way using .fromTo()
方法的忠实粉丝。