是否可以将 CSS 过渡设置为使用速度而不是持续时间?
现在,如果我想要一个将元素从另一个元素的左向右移动的类,速度会有很大差异。
如果我有短元素,并且我想将子元素从左向右移动,并且持续时间设置为例如1秒,比它移动得慢。
另一方面,如果我有一个非常长的同一类元素,那么子元素会以令人难以置信的速度闪烁以满足 1 秒的时间限制。
这确实损害了我的 CSS 模块化,所以我想知道是否有办法在这种情况下使过渡保持一致。
不,没有
transition-speed
css 属性,但是有一个 transition-timing-function-property
如果您使用该功能,您可以设置相对于持续时间的过渡速度,也可以使用步骤。根据规格:
“transition-timing-function”属性描述了如何 将计算转换期间使用的中间值。它 允许在其持续时间内改变速度的过渡。这些 效果通常称为缓动函数。在任何一种情况下, 使用提供平滑曲线的数学函数。
定时函数可以定义为步进函数或三次函数 贝塞尔曲线。计时功能将当前的输入作为其输入 过渡持续时间的经过百分比并输出 从起始值到当前值的转换方式的百分比 最终值。如何使用此输出由插值定义 值类型的规则。
步进函数由划分域的数字定义 操作成相等大小的间隔。每个后续间隔是 距离目标状态又近了一步。该函数还指定 产出百分比的变化是否发生在开始或结束时 间隔(换句话说,如果输入百分比的 0% 是 初始变化点)。
我相信这个转换计时函数属性是最接近你想要的东西,但我知道它与速度属性不同。
例如,考虑这个动画(具有固定的持续时间,因此速度可变):
@keyframes slideball {
0% { margin-left: 0px; }
100% { margin-left: calc(100% - 30px); }
}
.slider {
height: 30px;
background: blue;
border-radius: 20px;
margin: 10px;
padding: 5px;
}
#slider1 {
width: 80px;
}
#slider2 {
width: 200px;
}
#slider3 {
width: 500px;
}
.ball {
height: 30px;
width: 30px;
border-radius: 30px;
background: red;
animation: slideball linear 10s forwards;
}
<div id="slider1" class="slider">
<div class="ball"></div>
</div>
<div id="slider2" class="slider">
<div class="ball"></div>
</div>
<div id="slider3" class="slider">
<div class="ball"></div>
</div>
假设我们希望所有球都以每秒 40 像素的速度前进,无论包含它们的滑块有多宽。然后,我们可以在 JavaScript 中计算生成的动画持续时间,并从 JavaScript 设置
animation
样式属性:
function startAnimation(slider) {
const ball = slider.children[0],
speed = 40, // px per second
distancePx = (
slider.offsetWidth
- parseInt(getComputedStyle(slider).paddingLeft)
- parseInt(getComputedStyle(slider).paddingRight)
- ball.offsetWidth
),
duration = distancePx / speed;
ball.style.animation = `slideball linear ${duration}s forwards`;
}
startAnimation(document.getElementById('slider1'));
startAnimation(document.getElementById('slider2'));
startAnimation(document.getElementById('slider3'));
@keyframes slideball {
0% { margin-left: 0px; }
100% { margin-left: calc(100% - 30px); }
}
.slider {
height: 30px;
background: blue;
border-radius: 20px;
margin: 10px;
padding: 5px;
}
#slider1 {
width: 80px;
}
#slider2 {
width: 200px;
}
#slider3 {
width: 500px;
}
.ball {
height: 30px;
width: 30px;
border-radius: 30px;
background: red;
}
<div id="slider1" class="slider">
<div class="ball"></div>
</div>
<div id="slider2" class="slider">
<div class="ball"></div>
</div>
<div id="slider3" class="slider">
<div class="ball"></div>
</div>
是的,这有点冗长和烦人,特别是因为当你有一堆边距、填充和边框等时计算行驶的距离有时可能会变得有点……复杂。但 CSS 目前没有为您提供任何更好的工具可供使用,因此您只能采用这样的方法。
在示例 2 中,我通过将较大盒子的持续时间设置为 3 秒来补偿这一点,现在它们(几乎)具有相同的速度。
最好的方法可能是根据盒子的大小计算移动的距离,并使用该值来计算所需的持续时间,以使无论大小的盒子都以相同的速度移动。
.div1 div {
width: 100px;
height: 100px;
background-color: red;
position: relative;
animation-name: example1;
animation-duration: 4s;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
.div2 div {
width: 200px;
height: 200px;
background-color: blue;
position: relative;
animation-name: example2;
animation-duration: 4s;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
@keyframes example1 {
0% {left:0px; top:0px;}
100% {left:400px; top:0px;}
}
@keyframes example2 {
0% {left:0px; top:0px;}
100% {left:300px; top:0px;}
}
.div3 div {
width: 100px;
height: 100px;
background-color: red;
position: relative;
animation-name: example3;
animation-duration: 4s;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
.div4 div {
width: 200px;
height: 200px;
background-color: blue;
position: relative;
animation-name: example4;
animation-duration: 3s;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
@keyframes example3 {
0% {left:0px; top:0px;}
100% {left:400px; top:0px;}
}
@keyframes example4 {
0% {left:0px; top:0px;}
100% {left:300px; top:0px;}
}
<br>Sample 1<br>
<div class="div1">
<div></div>
</div>
<div class="div2">
<div></div>
</div>
<br>Sample 2<br>
<div class="div3">
<div></div>
</div>
<div class="div4">
<div></div>
</div>