在web應用中,前端同窗在實現動畫效果時每每經常使用的幾種方案:css
在大多數需求中,css3的 transition / animation
都能知足咱們的需求,而且相對於js實現,能夠大大提高咱們的開發效率,下降開發成本。html
本篇文章將着重對 animation
的使用作個總結,若是你的工做中動畫需求較多,相信本篇文章可以讓你有所收穫:前端
介紹完 animation 經常使用屬性,爲了將這些屬性更好地理解與運用,下面將手把手實現一些DEMO具體講述css3
經過修改內容在父元素中的y軸的位置來實現廣播效果git
@keyframes scroll {
0%{
transform: translate(0, 0);
}
100%{
transform: translate(0, -$height);
}
}
.ul {
animation-name: scroll;
animation-duration: 5s;
animation-timing-function: linear;
animation-iteration-count: infinite;
/* animation: scroll 5s linear infinite; 動畫屬性簡寫 */
}
複製代碼
此處爲了保存廣播滾動效果的連貫性,防止滾動到最後一幀時沒有內容,
須要多添加一條重複數據進行填充
github
<div class="ul">
<div class="li">小劉同窗加入了凹凸實驗室</div>
<div class="li">小鄧同窗加入了凹凸實驗室</div>
<div class="li">小李同窗加入了凹凸實驗室</div>
<div class="li">小王同窗加入了凹凸實驗室</div>
<!-- 插入用於填充的數據數據 -->
<div class="li">小劉同窗加入了凹凸實驗室</div>
</div>
複製代碼
經過將過渡動畫拆分爲多個階段,每一個階段的top屬性停留在不一樣的位置來實現web
/* 規定動畫,改變top,opacity */
@keyframes animate {
0% {
top: -100%;
opacity: 0;
}
25% {
top: 60;
opacity: 1;
}
50% {
top: 48%;
opacity: 1;
}
75% {
top: 52%;
opacity: 1;
}
100%{
top: 50%;
opacity: 1;
}
}
複製代碼
爲了讓過渡效果更天然,這裏經過
cubic-bezier()
函數定義一個貝塞爾曲線來控制動畫播放速度segmentfault
過渡動畫執行完後,爲了將讓元素應用動畫最後一幀的屬性值,咱們須要使用
animation-fill-mode: forwards
app
.popup {
animation-name: animate;
animation-duration: 0.5s;
animation-timing-function: cubic-bezier(0.21, 0.85, 1, 1);
animation-iteration-count: 1;
animation-fill-mode: forwards;
/* animation: animate 0.5s cubic-bezier(0.21, 0.85, 1, 1) 1 forwards; 動畫屬性簡寫 */
}
複製代碼
相信大多數同窗都知道點贊效果,本文章會實現一個簡易版的點贊效果,主要講述一下實現思路:svg
1.爲了讓氣泡能夠向上偏移,咱們須要先實現一個y軸方向上移動的 @keyframes 動畫
/* 規定動畫,改變y軸偏移距離*/
@keyframes animation-y {
0%{
transform: translate(-50%, 100px) scale(0);
}
50%{
transform: translate(-50%, -100px) scale(1.5);
}
100%{
transform: translate(-50%, -300px) scale(1.5);
}
}
複製代碼
2.爲了讓氣泡向上偏移時顯得不太單調,咱們能夠再實現一個x軸方向上移動的 @keyframes 動畫
/* 規定動畫,改變x軸偏移距離 */
@keyframes animation-x {
0%{
margin-left: 0px;
}
25%{
margin-left: 25px;
}
75%{
margin-left: -25px;
}
100%{
margin-left: 0px;
}
}
複製代碼
這裏我理解:
修改 margin
來改變x軸偏移距離,但實際上與修改 transform
沒有太大的性能差別@keyframes animation-y
中的 transform
已經新建了一個渲染層 ( PaintLayers )
animation
屬性 可讓該渲染層提高至 合成層(Compositing Layers)
擁有單獨的圖形層 ( GraphicsLayer )
,即開啓了硬件加速 ,不會影響其餘渲染層的 paint、layout
如筆者這裏理解有誤,還請讀者大佬指出,感激涕零~
3.給氣泡應用上咱們所實現的兩個 @keyframes 動畫
.bubble {
animation: animation-x 3s -2s linear infinite,animation-y 4s 0s linear 1;
/* 給 bubble 開啓了硬件加速 */
}
複製代碼
4.在點贊事件中,經過 js 操做動態添加/移除氣泡元素
function like() {
const likeDom = document.createElement('div');
likeDom.className = 'bubble'; // 添加樣式
document.body.appendChild(likeDom); // 添加元素
setTimeout( () => {
document.body.removeChild(likeDom); // 移除元素
}, 4000)
}
複製代碼
1.首先,咱們使用 svg 繪製一個圓周長爲2 * 25 * PI = 157
的圓
<svg with='200' height='200' viewBox="0 0 100 100" >
<circle cx="50" cy="50" r="25" fill="transparent" stroke-width="4" stroke="#0079f5" ></circie>
</svg>
複製代碼
2.將實線圓繪製成虛線圓,這裏須要用 stoke-dasharray:50, 50 (可簡寫爲50)
屬性來繪製虛線, stoke-dasharray 參考資料
短劃線(50px)
和缺口(50px)
的長度。50(短劃線) + 50(缺口) + 50(段劃線) = 150, 150 < 157
,沒法繪製出完整的圓,因此會致使右邊存在缺口(7px)
<svg with='200' height='200' viewBox="0 0 100 100" >
<circle cx="50" cy="50" r="25" fill="transparent" stroke-width="4" stroke-dasharray="50" stroke="#0079f5" ></circie>
</svg>
複製代碼
3.stroke-dashoffset
屬性可使圓的短劃線和缺口產生偏移,添加 @keyframes 動畫後可以實現從無到有的效果,stoke-dashoffset參考資料
stroke-dasharray="157 157
",指定 短劃線(157px)
和 缺口(157px)
的長度。修改stroke-dashoffset值
, 值爲正數
時逆時針偏移
🔄,, 值爲負數
時,順時針偏移
🔃@keyframes loading {
0%{
stroke-dashoffset: 0;
}
100%{
stroke-dashoffset: -157; /* 線條順時針偏移 */
}
}
circle{
animation: loading 1s 0s ease-out infinite;
}
複製代碼
4.修改短劃線和缺口值
50px
的短劃線,設置 stroke-dasharray="50"
缺口須要大於或等於圓周長157
,設置 stroke-dasharray="50 157"
動畫結束時仍處理動畫開始位置
,須要修改 stroke-dashoffset:-207(短劃線+缺口長度)
stroke-dashoffset
屬性,具體實現請查看示例@keyframes loading {
0%{
stroke-dashoffset: 0;
}
100%{
stroke-dashoffset: -207; /* 保證動畫結束時仍處理動畫開始位置 */
}
}
circle{
animation: loading 1s 0s ease-out infinite;
}
複製代碼
steps()
是 animation-timing-function
的屬性值
animation-timing-function : steps(number[, end | start])
複製代碼
兩個參數
第一個參數接受一個整數值
,表示兩個關鍵幀之間分幾步完成第二個參數有兩個值 start or end
。默認值爲 endsteps 適用於關鍵幀動畫,第一個參數將兩個關鍵幀
細分爲N幀
,第二個參數決定從一幀到另外一幀的中間間隔是用開始幀
仍是結束幀
來進行填充。
看下圖能夠發現:
steps(N, start)
將動畫分爲N段
,動畫在每一段的起點
發生階躍(即圖中的空心圓 → 實心圓),動畫結束時停留在了第N幀steps(N, end)
將動畫分爲N段
,動畫在每一段的終點
發生階躍(即圖中的空心圓 → 實心圓),動畫結束時第N幀已經被跳過(即圖中的空心圓 → 實心圓),停留在了N+1幀。13
個字符。[經測試,多數中文字體每一個字符寬高都相等]steps(13)
能夠將 @keyframes 動畫分爲13階段
運行,且每一階段運行距離相等
。效果以下:
/* 改變容器寬度 */
@keyframes animate-x {
0%{
width: 0;
}
}
p {
width: 125px;
overflow: hidden;
border-right: 1px solid transparent;
animation: animate-x 3s 0s steps(13) 1 forwards;
}
複製代碼
每一個字符的width與動畫每一階段運行的距離相等
Monaco
字體屬性,用以保證每一個字符的 width 相同
,具體像素受fontSize
屬性影響,示例中的字體寬度約爲 9.6px,9.6px * 13(段數) = 124.8px (125px)
,因此當咱們設置容器寬度爲 125px,便可的達成目的:每一個字符的 width 與動畫每一階段運行的距離相等(約爲 9.6px )
。p {
/* 設置 Monaco 字體屬性,字體大小爲16px,用以保證每一個字符的 width 相同,width 約爲9.6p */
font-family: Monaco;
/* 9.6px * 13 = 124.8px (125px) */
width: 125px ;
font-size: 16px;
overflow: hidden;
border-right: 1px solid transparent;
/* 同時應用動畫 animate-x、cursor-x */
animation: animate-x 3s 0s steps(13) 1 forwards,cursor-x 0.4s 0s linear infinite;
}
複製代碼
47幀
的雪碧圖(css spirit),設置背景圖.main {
width: 260px;
height: 200px;
background: url(url) no-repeat;
background-size: 100%;
background-position: 0 0;
}
複製代碼
修改 background-position
,讓背景圖移動@keyframes animate {
0% {
background-position: 0 0;
}
100% {
background-position: 0 100%;
}
}
.main{
width: 260px;
height: 200px;
background: url(url) no-repeat;
background-size: 100%;
background-position: 0 0;
animation: animate 2s 1s steps(47) infinite alternate;
}
複製代碼
animation-play-state
用於控制動畫是否暫停input:checked+.main{
animation-play-state: paused;
}
複製代碼
CSS 參考手冊
SVG學習之stroke-dasharray 和 stroke-dashoffset 詳解
理解CSS3 Animation中的steps()
【譯】css動畫裏的steps()用法詳解
CSS Will Change