css 中隨機(jī)、打字等動(dòng)畫的實(shí)現(xiàn)

背景知識(shí):css 動(dòng)畫規(guī)范
@keyframes
animation-name
animation-duration
animation-timing-function
animation-delay
animation-iteration-count
animation-direction
animation-play-state
animation-fill-mode

各屬性的定義及用法:

@keyframes: 用來指定CSS動(dòng)畫一次循環(huán)中,可以用百分比表示多個(gè)時(shí)間節(jié)點(diǎn)處的CSS屬性變化,關(guān)鍵字 from 等于 0%,to 等于 100%。

animation-name:指定@keyframes的名字,CSS加載時(shí)會(huì)應(yīng)用該名字的@keyframes規(guī)則來實(shí)現(xiàn)動(dòng)畫。

animation-duration:動(dòng)畫持續(xù)時(shí)間,默認(rèn)是0表示無動(dòng)畫,單位可以設(shè)s秒或ms毫秒。

animation-timing-function:動(dòng)畫播放方式,默認(rèn)值ease,可以設(shè)linear,ease,ease-in,ease-out,ease-in-out,cubic-bezier(n,n,n,n),steps。

animation-delay:延遲開始動(dòng)畫的時(shí)間,默認(rèn)值是0,表示不延遲,立即播放動(dòng)畫。單位是s秒或ms毫秒。允許設(shè)負(fù)時(shí)間,意思是讓動(dòng)畫動(dòng)作從該時(shí)間點(diǎn)開始啟動(dòng),之前的動(dòng)畫不顯示。例如 -3s 使動(dòng)畫馬上開始,但前 3 秒的動(dòng)畫被跳過。

animation-iteration-count:動(dòng)畫循環(huán)播放的次數(shù),默認(rèn)值為1,即放完一遍后不循環(huán)播放。除數(shù)字外也可以設(shè)關(guān)鍵字 infinite 表示無限循環(huán)播放。

animation-direction:動(dòng)畫播放的方向,可設(shè)normal,alternate,alternate-reverse。默認(rèn)值是 normal 表示正常播放動(dòng)畫。alternate 表示輪轉(zhuǎn)正反向播放動(dòng)畫,即動(dòng)畫會(huì)在奇數(shù)次(1,3,5…)正常播放,而在偶數(shù)次(2,4,6…)反向播放。alternate-reverse 正好反過來,奇數(shù)次反向播動(dòng)畫,偶數(shù)次正向播動(dòng)畫。

animation-play-state:動(dòng)畫的狀態(tài),可設(shè)running,paused。默認(rèn)值 running 表示正在播放動(dòng)畫,paused 表示暫停動(dòng)畫。

animation-fill-mode:動(dòng)畫的時(shí)間外屬性,可設(shè) none,forwards,backwards,both。默認(rèn)值 none 表示動(dòng)畫播完后,恢復(fù)到初始狀態(tài)。forwards 當(dāng)動(dòng)畫播完后,保持 @keyframes 里最后一幀的屬性。backwards 表示開始播動(dòng)畫時(shí),應(yīng)用 @keyframes 里第一幀的屬性,要看出效果,通常要設(shè) animation-delay 延遲時(shí)間。both 表示 forwards 和 backforwards 都應(yīng)用。

接下來看看幾個(gè)比較實(shí)用的動(dòng)畫實(shí)現(xiàn)吧:

一、隨機(jī)動(dòng)畫

隨機(jī)動(dòng)畫

代碼示例:

<p class="loading">Loading…</p>

@keyframes spin { to { transform: rotate(1turn); } }
@keyframes radius { 50% { border-radius: 50%; } }
@keyframes color { 33% { color: orange; } 66% { color: deeppink; } }
@keyframes width { 50% { border-width: .3em; } }

.loading:before {
    content: '';
    display: block;
    width: 4em;
    height: 4em;
    margin: 0 auto 1em;
    border: 1.5em solid;
    color: yellowgreen;
    box-sizing: border-box;
    animation: 1s spin, .7s radius, 1.1s color, 1.3s width;
    animation-timing-function: ease;
    animation-iteration-count: infinite;
}

.loading {
    margin: auto;
}

二、逐幀動(dòng)畫

需要利用合成好的背景圖,如下:


loader
逐幀動(dòng)畫

代碼示例:

<div class="loader">loading...</div>

@keyframes loader {
    to {
        background-position: -800px 0;
    }
}
.loader {
    width: 100px;
    height: 100px;
    margin: auto;
    background: url("img/loader.png");
    /*隱藏文字*/
    overflow: hidden;
    text-indent: 999px;
    /*這里需要借助css3的控制時(shí)間的屬性steps 階躍函數(shù),還有一個(gè)控制時(shí)間的屬性的函數(shù)是貝塞爾曲線*/
    animation: 1s loader infinite steps(8);
}

這里用到了 steps 階躍函數(shù)。
語法:steps(n, start/end)
第一個(gè)參數(shù) n 是一個(gè)正整數(shù),表示階躍次數(shù),
第二個(gè)參數(shù)start或end,表示階躍點(diǎn),
start 表示一開始就先進(jìn)行階躍,end 表示每階段完成后再進(jìn)行階躍,
默認(rèn)值為 end。
階躍時(shí)間函數(shù)如下:

階躍start-end
階躍時(shí)間曲線

注意點(diǎn):
階躍函數(shù) steps 指的是 @keyframes 中各環(huán)節(jié)之間的時(shí)間變換函數(shù),
它并不是指整個(gè) @keyframes 動(dòng)畫階躍幾次,
如果需要每個(gè)環(huán)節(jié)到下一個(gè)環(huán)節(jié)只階躍一次,可設(shè)置為 steps(1, start/end)。

三、閃爍效果

閃爍效果

代碼示例:

<p class="blink1">最普通的閃爍效果:需要借助 steps() 階躍函數(shù),而且必須把關(guān)鍵幀設(shè)置在中間</p>
<p class="blink2">平滑的閃爍效果:讓關(guān)鍵幀設(shè)置在中間50%的位置</p>
<p class="blink3">更加逼真的閃爍效果:需要把循環(huán)的次數(shù)翻倍且要交替出現(xiàn),循環(huán)的時(shí)間設(shè)置為上面的一半</p>

@keyframes blink-smooth1 {
    50% {
        color: transparent;
    }
}

@keyframes blink-smooth2 {
    to {
        color: transparent;
    }
}

p {
    padding: 1em;
    background: gold;
}

.blink1 {
    animation: 2s blink-smooth1 3 steps(1);
}

.blink2 {
    animation: 2s blink-smooth1 3;
}

.blink3 {
    animation: 1s blink-smooth2 6 alternate;
}

四、緩動(dòng)效果

緩動(dòng)效果

代碼示例:

<div class="ball">三次貝塞爾曲線</div>

@keyframes bounce {
    60%, 80%, to {
        -webkit-transform: translateY(400px);
            -moz-transform: translateY(400px);
            -ms-transform: translateY(400px);
                -o-transform: translateY(400px);
                transform: translateY(400px);
    animation-timing-function: ease;
    }
    70% {-webkit-transform: translateY(300px);
        -moz-transform: translateY(300px);
        -ms-transform: translateY(300px);
            -o-transform: translateY(300px);
            transform: translateY(300px);}
    90% {
        -webkit-transform: translateY(360px);
            -moz-transform: translateY(360px);
            -ms-transform: translateY(360px);
                -o-transform: translateY(360px);
                transform: translateY(360px);
    }
}
.ball {
    width: 0;
    height: 0;
    padding: 2.5em;
    margin: auto;
    border-radius: 50%;
    /*at 50% 50% 是指圓心的位置*/
    background: radial-gradient(at 30% 30%, #fdd, red);
    animation: bounce 3s cubic-bezier(.215, .61, .355, 1) forwards;
}
body {
    min-height: 100vh;
    background: linear-gradient(skyblue, white 450px, yellowgreen 0);
}

這個(gè)效果是通過另一個(gè)階躍函數(shù):cubic-bezier 函數(shù)。
主要是借用三次貝塞爾曲線來實(shí)現(xiàn)的。

語法:cubic-bezier(x1, y1, x2, y2)
(x1, y1) 表示第一個(gè)控制錨點(diǎn)的坐標(biāo),而 (x2, y2) 是第二個(gè)。
曲線片斷的兩個(gè)端點(diǎn)分別固定在 (0,0) 和 (1,1),前者是整個(gè)過渡的起點(diǎn)(時(shí)間進(jìn)度為零,動(dòng)畫進(jìn)度為零),后者是終點(diǎn)(時(shí)間進(jìn)度為 100%,動(dòng)畫進(jìn)度為 100%)。
固定曲線的兩個(gè)端點(diǎn)并不是唯一的限制。兩個(gè)控制錨點(diǎn)的 x 值都被限制在 [0, 1] 區(qū)間內(nèi)(即我們無法把手柄在水平方向上移出這個(gè)圖形范圍)。這個(gè)限制并不是隨便加上的。

之前如 ease、linear、ease-in、ease-out、ease-in-out 這五個(gè)已有的效果都是 cubic-bezier 實(shí)現(xiàn)的,具體值如下:

ease: cubic-bezier(0.25, 0.1, 0.25, 1.0)
linear: cubic-bezier(0.0, 0.0, 1.0, 1.0)
ease-in: cubic-bezier(0.42, 0, 1.0, 1.0)
ease-out: cubic-bezier(0, 0, 0.58, 1.0)
ease-in-out: cubic-bezier(0.42, 0, 0.58, 1.0)
貝塞爾曲線

這個(gè)動(dòng)畫并沒有使用上面五個(gè)已有的動(dòng)畫,需要在 cubic-bezier 上調(diào)試出更加平滑的參數(shù),如例子中的 cubic-bezier(.215, .61, .355, 1) 就是通過此網(wǎng)站調(diào)試的。

五、狀態(tài)平滑的動(dòng)畫

狀態(tài)平滑的動(dòng)畫

代碼示例:

<div class="state-animation"></div>

@keyframes state {
    to {
        background-position: 100% 100%;
    }
}
.state-animation { 
    width: 250px;
    height: 250px;
    background: url("img/timg.jpg");
    background-size: auto 100%;
    animation: state 10s linear infinite alternate;
    /*這里需要?jiǎng)赢嫷腶nimate-play-state屬性*/
    animation-play-state: paused;
}
.state-animation:hover, .state-animation:focus {
    /*通過動(dòng)畫的播放狀態(tài)來實(shí)現(xiàn)動(dòng)畫的平滑度*/
    animation-play-state: running;
}

六、打字動(dòng)畫

打字動(dòng)畫

代碼示例:

<h1>CSS is awesome!</h1>
@keyframes typing {
    from {
        width: 0;
    }
}

@keyframes caret {
    50% {
        border-color: transparent;
    }
}

h1 {
    width: 15ch;
    overflow: hidden;
    white-space: nowrap;
    border-right: .05em solid;
    animation: typing 8s steps(15), caret 1s steps(1) infinite;
    font: bold 200% Consolas, Monaco, monospace;
}

這里引入了一個(gè)新的 css 單位 ch,它是以 0 的寬度為參考的,在等寬字體中,所有的字體與 0 的寬度是一樣的;如果要加上閃爍的光標(biāo),需要借助右邊框來實(shí)現(xiàn)。
因單行的字符數(shù)量不定,css 維護(hù)不便,為了更易于維護(hù),需要借助 javascript 來實(shí)現(xiàn),如下代碼:

function $$(selector, context) {
    context = context || document;
    let elements = context.querySelectorAll(selector);
    return Array.prototype.slice.call(elements);
}
$$("h1").forEach(function(h1) {
    let len = h1.textContent.length, s = h1.style;

    s.width = len + "ch";
    s.animationTimingFunction = "steps(" + len + "),steps(1)";
});  

七、沿環(huán)形路徑平移的動(dòng)畫

環(huán)形動(dòng)畫

代碼示例:

<div class="circular2">
    <img src="img/me.jpg" height="960" width="1280" alt="" />
</div>

/*為同一個(gè)元素指定多個(gè)變形原點(diǎn)*/
@keyframes spin2 {
    from {
        transform: translateY(150px) translateY(-50%)
                    rotate(0turn)
                    translateY(-150px) translateY(50%)
                    rotate(1turn);
    }
    to {
        transform: translateY(150px) translateY(-50%)
                    rotate(1turn)
                    translateY(-150px) translateY(50%)
                    rotate(0turn);
    }
}

.circular2 {
    margin: 50px auto;
    width: 300px;
    height: 300px;
    background: gold;
    border-radius: 50%;
}

.circular2 img {
    display: block;
    margin: 20px auto;
    width: 50px;
    height: 50px;
    border-radius: 50%;
}    

更多動(dòng)畫效果可以參看 animate.css 庫,這里有很多動(dòng)畫,可以參看源碼。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容