百度前端技術學院2017于2月24日開始進行,一共有6個學院可供學習,分別是小薇學院(html/css基礎)、斌斌學院(js基礎)、耀耀學院(小游戲/交互)、商業平臺學院(web/ios/android)、ECharts & WebVR學院(VR相關)和糯米學院(css3/vue等),從百度前端技術學院今年推出的各學院任務看來,目前互聯網行業對從事前端行業的程序員要求越發高了。轉行前端或是才開始學習前端的同學任重而道遠,大家一起加油,共勉。
《CSS3圓餅loading效果》作為糯米學院中的進階任務,目的主要是讓學員通過完成任務,掌握border-radius屬性的使用以及旋轉動畫的設置。在已經完成鼠標懸浮效果任務之后,相對來說本任務要簡單很多。以下是總結。
任務分解:該任務要達到的效果。如網頁中顯示情況,可將任務分解為兩個小任務:
1.制作四分之三圓環并旋轉;
2.制作圓餅,圓餅內有兩種顏色,分別交替旋轉擴大其扇形區域(從0deg到到360deg),以達到圓餅loading效果。
通過完成任務,使用到如下一些重要屬性:
1.制作圓環,使用偽元素,使用border(包括其transparent值);
2.制作圓餅過程中,使用到animation-timing-function屬性的steps()曲線;
3.圓餅及圓環的旋轉,使用animation系列屬性,并使用transform設置旋轉角度,使用transform-origin屬性設置旋轉中心。
以下是完成本任務后的html結構:
<header>
<h1><a >小星的博客|Small Star's Blog</a></h1>
<ul>
<li><a href="#top-bottom1">點我</a></li>
<li><a href="#top-bottom2">快點我</a></li>
<li><a href="#top-bottom3">點我吧</a></li>
<li><a href="#top-bottom4">點我啦</a></li>
</ul>
</header>
<article>
<p class="round1">
<span class="bgcircle">
<span class="left"><span class="spining"></span></span>
<span class="right"><span class="spining"></span></span>
</span>
</p>
<p class="round2">
<span class="bgcircle">
<span class="inner">
<span class="spiner"></span>
<span class="filler"></span>
<span class="masker"></span>
</span>
<span class="inner2">
<span class="spiner"></span>
<span class="filler"></span>
<span class="masker"></span>
</span>
</span>
</p>
</article>
<footer>
<p>版權所有 © 小星</p>
</footer>
</body>
</html>
其中,round1為使用第一種方法制作圓餅時的loading整體結構,round2為使用第二種方法制作圓餅時的loading整體結構。可以明顯發現round2方法結構復雜,實際上其實現方法也較round1方法笨拙。結構樣式代碼請見文末demo代碼地址。頁面圖如下:
圓環及圓餅制作原理如下:
1.四分之三圓環的旋轉:
實現原理:首先將上文html結構中的類名為bgcircle的span元素設置為圓形(將其border-radius設置為50%即可),其寬高大于兩個子元素span,以便圓環與圓餅分開。在.bgcircle上設置偽元素,同樣設置為圓形,大小與.bgcircle相同,再設置偽元素邊框,其中任一邊框設置為transparent即可。最后利用animotion和transform設置旋轉動畫。css代碼如下:
/*2-1-1.制作大圓背景*/
.bgcircle{
position:relative;
display:inline-block;
height:80px;
width:80px;
margin:50% 0 0 50%;
top:-30px;
left:-30px;
border-radius:50%;
overflow:hidden;
}
/*2-2.loading圓環*/
.bgcircle::before{
content:"";
position:absolute;
width:100%;
height:100%;
box-sizing:border-box;
border:4px solid #BD50A3;
border-top:4px solid transparent;
border-radius:50%;
-webkit-animation:circle-spining 4s infinite linear;
animation:circle-spining 4s infinite linear;
-webkit-transform-origin:50% 50% 0;
transform-origin:50% 50% 0;
}
@keyframes circle-spining{
0%{transform:rotate(0deg);}
50%{transform:rotate(-180deg);}
100%{transform:rotate(-360deg);}
}
@-webkit-keyframes circle-spining{
0%{-webkit-transform:rotate(0deg);}
50%{-webkit-transform:rotate(-180deg);}
100%{-webkit-transform:rotate(-360deg);}
}
2.圓餅旋轉:
(1)方法一:主要參考codepen網站中Geoffrey Crofte的CSS Loaderdemo,其中也寫了一些其他loading效果。總體來說,這些loading效果的主要原理都是:在.bgcircle之下,設置.left、.right為左右半圓,拼接為一個圓餅,對.left,設置其子元素.spining往右移至.right區域,并形成半圓與.right區域重疊,此時只有.spining旋轉至.left區域時才能顯示出來。同理,設置了.right的子元素.spining。最后,對兩個.spining子元素設置不同的旋轉動畫已達到要求效果。css代碼過長,請見文末demo代碼地址,其旋轉過程如下步驟表述:
a.初始狀態下,兩個.spining都沒有旋轉(圖中深紫色圓餅):此時.left.spining圍繞圓心開始逆時針旋轉,至-180deg:
b.“.left.spining”圍繞圓心開始逆時針旋轉,至-180deg(圖中淺紫色半圓):
c.“.left.spining”停止旋轉,“.right.spining”開始旋轉至-180deg,此時兩個.spining都顯示出來了,形成淺紫色圓餅:
d.“.right.spining”停止旋轉,“.left.spining”又開始旋轉,從-180deg旋轉至-360deg,此時只剩下“.right.spining”形成的淺紫色右半圓:
e.“.left.spining”一周的旋轉動畫結束,停止旋轉;“.right.spining”開始最后半周的旋轉,至-360deg停止。整個一周的動畫結束。對此動畫設置無限循環次數,即可達到最終效果。
(2)方法二:參考張鑫旭博客的文章CSS3實現雞蛋餅餅狀圖loading等待轉轉轉,在張鑫旭前輩的這篇文章里,利用比喻把他的方法原理表述的很清楚,簡單來說:他將動畫分成了兩半,如果以本文前面頁面圖中右邊的圓餅作為例子的話,前半動畫是深藍色由12點鐘位置開始逆時針旋轉至-360deg,最后將橙色覆蓋;后半動畫剛好相反,橙色由12點鐘位置開始逆時針旋轉至-360deg,最后將深藍色覆蓋。由于兩半部分動畫的過程是相同的,所以將前半部分動畫制作完成后,將該動畫過程復制一份,將顏色對調,重新套入相同結構的新元素中,再將新的一套重疊在舊一套元素所占區域,設置前半段時間第一套元素顯示、第二套元素透明,后半段時間第二套元素顯示、第一套元素透明。這樣就完成了圓餅loading效果。
下面以前半部分動畫為例表述下動畫過程:
首先需要了解html結構(以本文開始所列html結構為例),設置類名為inner的span作為父元素,該元素背景為深藍色,其下同列三個span作為子元素,類名分別為:spiner、filler、masker。以上四者中,按照原理,.filler、.masker的z-index應該設置得高于.spiner,但在實際設置中,張鑫旭前輩沒有設置z-index值,而是利用在html結構中將需要優先顯示的元素并列在后面的方式(如果在html結構中將.masker與.spiner對調,就會出現錯誤),規避了這點。.masker為左半圓,深藍色;.filler為右半圓,橙色;.spiner為旋轉半圓,橙色,初始位置位于左半部分。
a.初始狀態:.masker透明,此時由.spiner和.filler分別位于左右方拼接成橙色圓餅:
b.此時,.spiner開始圍繞圓心逆時針旋轉,則作為父元素的.inner開始從12點鐘方向逆時針顯露(深藍色),到.spiner旋轉-180deg時,.masker由透明變為顯示,.filler由顯示變為透明:
c.之后,.spiner繼續逆時針旋轉,由于.filler已經透明,則.inner從6點鐘方向逆時針顯露,而左半圓區域由于.masker已經顯示(z-index值比.spiner大),也為深藍色,這樣,當.spiner旋轉一周之后,就由橙色全部變為藍色:
以上為動畫原理,css代碼過長,請見文末demo代碼地址。在實現這個方法的過程中,還需要注意,要變化透明度的元素(.inner/.inner2/.masker/.filler),其透明度變化并不是漸變,而是突變,所以需要設置animation-timing-function為steps()突變曲線,steps(n,start/end)主要有兩個值,簡單來說,n設置突變次數(整數),start/end設置在動畫開始還是結束突變。
思考:
1.利用steps()曲線,可以制作一些更炫酷的css3動畫。并且,在同一個方向上連續漸變的動畫,由于漸變位置不同,通常需要兩個以上元素實現,但利用steps()曲線突變位置,就能通過一個元素實現了;
2.完成以上任務之后,可以優化的地方:第一個方法中的.spining子元素,可以使用偽元素替代;同理,第二個方法中的子元素,也可用偽元素替代;
3.圓環除了定長旋轉,也可根據圓餅loading旋轉的方法,實現變長旋轉loading效果。
具體參考已在文中引出,不再單列,以下為我的demo及demo代碼: