移動端圓環進度動畫方案(透明背景-透明度圓環-css3版)
適逢元旦假期,妹子逛街吃火鍋看電影陪女朋友之際,像風一樣的寫完了這篇文章!文章畫風略微粗糙,但是這個動畫的實現還是很費了一番腦子的,話說程序猿之間交流并不需要過多解釋,上代碼就搞定。
首先說一下我們這個要實現的圓環進度動畫,有三個特點: 1、背景是透明的,所以用遮擋實現的方法就不用考慮了; 2、圓環顏色是有透明度的,所以用兩個半圓環實現大于180度的圓環效果不能有疊加部分; 3、最好用純css3簡潔的實現。 然后要備注下重點: 我們的動畫效果要應用在移動端,尤其是有些性能較差的安卓手機,所以一定要考慮性能問題。
先上效果圖:
: 對于不可用遮擋來實現的圓環動畫效果,我們可以用兩個半圓環的運動來組合,動畫效果使用transition和transform實現。 圓環小于50%時:
圓環大于50%時,由兩個不重疊的圓環組合而成:
所以對于大于50%的圓環旋轉動畫,是需要兩段動畫拼接的,左半邊的圓環先旋轉180度到右半邊,右半邊的圓環再旋轉相應的度數至左半邊,這里旋轉角度不是固定的,需要根據具體進度確定,所以這種方案右半邊的圓環旋轉多少度是通過js賦值的,那么問題來了,當我們在pc上看到流暢的旋轉動畫時,在安卓手機上,兩個半圓環動畫的銜接處, 有時差!不流暢!
思考下第一版方案失敗的根本原因,就是整個圓環進度是由兩個半圓環分別動畫形成的,右側圓環的旋轉角度不是固定的,使用transition實現需要通過js動態添加旋轉角度樣式,js語句的執行使得兩個圓環執行動畫的時間差無法確定,在性能較差的安卓手機上會明顯感覺到兩個動畫直接的銜接卡頓。
那么換一種思維方式,我們有了第二版解決方案,利用純css控制兩個半圓環動畫的執行,讓兩個半圓環動畫都固定旋轉180度,時間差固定,我們要控制的就是 可視區域的角度 。 這里只討論角度大于50%的情況,因為小于50%的情況無論用哪種方案都能實現。 上面我們討論過,右半邊不可見區域的圓環旋轉到左半邊時,整個左半邊都是可見區域,所以我們旋轉180度后當然能看見完整的半圓環,那我們嘗試著根據我們需要的角度縮小左半邊的可見區域不就可以了。(最后一幅圖太困了,改天再補!)
具體來講,我們實現右半邊可見圓環用了兩層,實現左半邊可見圓環用了三層,兩個圓環從左到右、從右到左分別旋轉180度,最后我們可以完整的看到整個右半側圓環,而左半側的圓環因為還有一層遮擋,只能看到我們所需進度的相應角度。
<div class="my-circle" id="my-circle"> <div class="right-outter"> <div class="right-inner"></div> </div> <div id="left-outter-patch" class="left-outter-patch"> <div id="left-outter" class="left-outter"> <div id="left-inner" class="left-inner"> </div> </div> </div> </div>
.my-circle { position: relative; width: 58px; height: 58px; } .right-outter { position: absolute; width: 29px; height: 58px; top: 0; right: 0; overflow: hidden; transform: rotate(180deg); -webkit-transform: rotate(180deg); } .right-inner { position: absolute; top: 0; left: 0; width: 50px; height: 50px; border-radius: 50%; border: 4px solid rgba(113, 222, 130, 0.3); clip: rect(0 58px 58px 29px); } .left-outter { position: absolute; width: 58px; height: 58px; top: 0; left: 0; overflow: hidden; clip: rect(0 58px 58px 29px); } .left-inner { position: absolute; top: 0; left: 0; width: 50px; height: 50px; border-radius: 50%; border: 4px solid rgba(113, 222, 130, 0.3); clip: rect(0 58px 58px 29px); transform: rotate(180deg); -webkit-transform: rotate(180deg); } .left-outter-patch { position: absolute; width: 58px; height: 58px; top: 0; left: 0; overflow: hidden; clip: rect(0 58px 58px 29px); } .test-animation .right-inner { transform: rotate(180deg); -webkit-transform: rotate(180deg); transition: transform 1s linear; -webkit-transition: -webkit-transform 1s linear; } .test-animation .left-inner { transform: rotate(360deg); -webkit-transform: rotate(360deg); transition: transform 1s linear 1s; -webkit-transition: -webkit-transform 1s linear 1s; }
所以動畫是由css固定實現的,而左半側的可視區域是由js代碼控制的,這樣無任何時差問題
var degree = 75; document.getElementById("left-outter-patch").style.transform = "rotate(" + ((degree-50)*360/100) + "deg)"; document.getElementById("left-outter-patch").style.WebkitTransform = "rotate(" + ((degree-50)*360/100) + "deg)"; document.getElementById("left-outter").style.transform = "rotate(" + (180-(degree-50)*360/100) + "deg)"; document.getElementById("left-outter").style.WebkitTransform = "rotate(" + (180-(degree-50)*360/100) + "deg)"; document.getElementById("my-circle").className = "my-circle test-animation";