如何理解 CSS step 函數(shù)中的 jump-* 關(guān)鍵詞?
之前在這篇文章中:CSS 實(shí)現(xiàn) Ant Design官網(wǎng)Logo彩蛋效果[1]實(shí)現(xiàn)了一個鼠標(biāo) hover 效果,如下
Kapture 2022-01-25 at 10.33.11
原理其實(shí)很簡單,就是一個 CSS 動畫,使用的是steps階梯函數(shù),不斷改變background-position
.logo{
animation: random 1s steps(10) infinite;
}
@keyframes random {
to {
background-position: 100%;
}
}
里面用到的小圖標(biāo)是這樣一張圖片(11個小圖標(biāo))
乍一看,動畫好像非常完美,其實(shí)還是有一個小小的缺陷,仔細(xì)觀察,最后一個圖標(biāo)(點(diǎn)贊圖標(biāo))一直沒有出現(xiàn)過,直接被跳過了,文章評論中也有人提到并給出解決方案
但是這種方式不太穩(wěn)定,background-potion需要考慮實(shí)際的幀數(shù),也就是需要根據(jù)steps的步數(shù)改變。
除了這種方式,其實(shí)還有更好的解決方案,今天就一起來探討這個問題
一、問題重現(xiàn)
為了方便觀察和演示,這里用1、2、3來做一張序列幀圖片,如下
然后通過 steps階梯函數(shù)實(shí)現(xiàn)序列幀動畫,關(guān)鍵實(shí)現(xiàn)如下
div{
animation: random 1s steps(2) infinite;
}
@keyframes random {
to {
background-position: 100%;
}
}
效果是這樣的(丟失了最后一幀)
Kapture 2023-06-11 at 16.23.09
為啥這里明明有 3 幀,卻要設(shè)置steps的次數(shù)為 2 ?我們不妨設(shè)置為 3 試試
animation: random 1s steps(3) infinite;
效果如下
情況就更加糟糕了,而且并不是按照1、2、3的邊界變化的,還出現(xiàn)了中間過渡狀態(tài),顯然不是我們想要的效果。
要搞清楚這個問題,需要理解steps函數(shù)中的第 2 個參數(shù),繼續(xù)往下看。
二、 steps 中的首尾幀忽略規(guī)則
steps其實(shí)有兩個參數(shù),官方語法如下
steps( <integer> [, <step-position> ]? )
現(xiàn)在再來看前面的寫法
steps(2)
這其實(shí)是一個簡寫,等同于
steps(2, end)
這是什么意思呢,end表示結(jié)束,也就是忽略最后一幀,所以上面的例子中,雖然有 3 幀,但忽略最后一幀后就只有 2 幀了,如下
在動畫中就是這樣,1→2→1→2...
所以,steps(2)表示將原圖片分成 3 幀,但是只運(yùn)行前面 2 幀,最后一幀跳過。
那么,上面的steps(3)也很好理解了吧,將原圖片平均分成了 4 份,所以就出現(xiàn)了中間過渡狀態(tài)
除了end以外,還有一個start
steps(2, start)
start表示開始,也就是忽略最前面的一幀
在動畫中就是這樣,2→3→2→3...
Kapture 2023-06-11 at 16.44.54
所以,steps(2,start)表示將原圖片分成 3 幀,但是只運(yùn)行后面 2 幀,跳過了第一幀。
那么,有沒有辦法分成多少幀就運(yùn)行多少幀呢?當(dāng)然也是有的,就是后來更新的jump-*關(guān)鍵詞
三、steps 中jumb-*關(guān)鍵詞
從 Chrome 77+開始,steps支持了幾個以jumb-開頭的關(guān)鍵詞,分別是
- jump-start,等同于之前的start,表示跳過第一幀
- jump-end,等同于之前的end,表示跳過最后一幀
- jump-both,表示跳過第一幀和最后一幀
- jump-none,表示都不跳過
下面是官方的一個函數(shù)圖像(每個實(shí)心點(diǎn)表示一幀)
其實(shí)我還是比較習(xí)慣于用跳過來理解,前面兩個就不說了,先看jumb-both
steps(1, jump-both)
去除首尾兩幀后,就只剩下中間一幀了,示意如下
image-20230611170734032
最后的動畫效果也只有中間一幀了,2→2→2→2...
然后是jump-none
steps(3, jump-none)
表示不跳過,有多少幀就運(yùn)行多少幀
動畫效果就是正常的1、2、3依次變化,1→2→3→1→2→3...
Kapture 2023-06-11 at 17.11.28
根據(jù)這個原理,文章開頭的小缺陷就非常好解決了,將steps(10)改為steps(11, jump-none)即可
.logo{
animation: random 1s steps(11, jump-none) infinite;
}
@keyframes random {
to {
background-position: 100%;
}
}
這樣就可以正常的看到最后一個圖標(biāo)了
你也可以訪問以下任意鏈接:
- CSS ant design logo fix (codepen.io)[2]
- CSS ant design logo fix (juejin.cn)[3]
- CSS ant design logo fix (runjs.work)[4]
之前的效果(注意對比觀察最后一個點(diǎn)贊圖標(biāo))
- Ant Design Logo (codepen.io)[5]
四、最后總結(jié)一下
其實(shí)這個特性也已經(jīng)出來好幾年了,但是好像很少有人知道,主要原因是這個特性使用場景不太豐富,并且有替代方案,再者,這個特性是舊屬性的補(bǔ)充,導(dǎo)致在文檔上不易輕易被發(fā)現(xiàn)(我也是無意發(fā)現(xiàn)的??)。兼容性方面,Safari還是有些拉胯,需要14+才行,完整兼容性如下: