下雪效果只是一類效果的名稱,可以是紅包雨等一些自由落體的運(yùn)動(dòng)效果,本文就是用純
css
模擬下雪的效果,更多效果大家可以自行發(fā)揮。
成都創(chuàng)新互聯(lián)一直通過(guò)網(wǎng)站建設(shè)和網(wǎng)站營(yíng)銷幫助企業(yè)獲得更多客戶資源。 以"深度挖掘,量身打造,注重實(shí)效"的一站式服務(wù),以網(wǎng)站設(shè)計(jì)制作、做網(wǎng)站、移動(dòng)互聯(lián)產(chǎn)品、營(yíng)銷型網(wǎng)站服務(wù)為核心業(yè)務(wù)。十余年網(wǎng)站制作的經(jīng)驗(yàn),使用新網(wǎng)站建設(shè)技術(shù),全新開(kāi)發(fā)出的標(biāo)準(zhǔn)網(wǎng)站,不但價(jià)格便宜而且實(shí)用、靈活,特別適合中小公司網(wǎng)站制作。網(wǎng)站管理系統(tǒng)簡(jiǎn)單易用,維護(hù)方便,您可以完全操作網(wǎng)站資料,是中小公司快速網(wǎng)站建設(shè)的選擇。
由于公司產(chǎn)品的活動(dòng),需要模擬類似下雪的效果。瀏覽器實(shí)現(xiàn)動(dòng)畫(huà)無(wú)非
css3
和
canvas
(還有
gif
),對(duì)比下
css3
和
canvas
的優(yōu)缺點(diǎn):
canvas
勝;
canvas
勝;
canvas
勝;
css3
勝(
requestAnimationFrame
和硬件加速)。由于對(duì)于性能有一定的要求,
canvas
對(duì)比
css3
會(huì)有更多的計(jì)算量導(dǎo)致性能可能不太好,所以選用
css3
模擬下雪效果(ps:能用
css
解決的問(wèn)題就不用
javascript
解決哈哈)。
本文所采用的是
css3
的
animation
。為
dom
元素添加
animation
屬性就可以模擬動(dòng)畫(huà),例如w3school的例子:
animation
當(dāng)然這誰(shuí)都會(huì),但有個(gè)問(wèn)題是,下雪并不是機(jī)械的下落,而是有快有慢、擺動(dòng)幅度、時(shí)間不定,這里的重點(diǎn)是需要構(gòu)造隨機(jī)性,理性分析下。
我們可以在css中找到這幾點(diǎn)隨機(jī)性的對(duì)應(yīng)屬性:
position
的左右方位(動(dòng)畫(huà)我們一般采用定位,因?yàn)榭梢詼p少不必要的重排和重繪);
animation-timing-function
(提供了豐富的速度屬性);
animation-duration
和
animation-delay
;
transform: translateX()
(在水平方向上的位移)。可能有人會(huì)問(wèn),這幾個(gè)屬性并不是隨機(jī)的呀,并不像
Math.random
隨機(jī)函數(shù)那樣。我們換個(gè)思考方向,本文所說(shuō)的隨機(jī)是隨機(jī)雪,并不是隨機(jī)雪的屬性。每個(gè)雪的下落時(shí)間、下落速度、擺動(dòng)幅度是固定的,雪與雪之間的下落時(shí)間、下落速度、擺動(dòng)幅度是不同,那么就達(dá)到效果了。
意識(shí)到這點(diǎn),就剩下最后一個(gè)問(wèn)題,怎樣給每個(gè)雪不同的下落時(shí)間、下落速度、擺動(dòng)幅度呢?這里我們使用真正的隨機(jī)函數(shù)
Math.random
,利用data自定義屬性配合
Math.random
和css的屬性匹配規(guī)則,就可以確定動(dòng)畫(huà)效果了。
.linear{ width: 100px; height: 100px; background: linear-gradient(0, green 40%, red 40%, red 60%, green 60%); }
.linear{ width: 100px; height: 100px; border-radius: 50%; background-image: linear-gradient(0, rgba(255,255,255,0) 40%, #fff 40%, #fff 60%, rgba(255,255,255,0) 60%), linear-gradient(45deg, rgba(255,255,255,0) 43%, #fff 43%, #fff 57%, rgba(255,255,255,0) 57%), linear-gradient(90deg, rgba(255,255,255,0) 40%, #fff 40%, #fff 60%, rgba(255,255,255,0) 60%), linear-gradient(135deg, rgba(255,255,255,0) 43%, #fff 43%, #fff 57%, rgba(255,255,255,0) 57%); }
我用
sass
寫(xiě)的
css
來(lái)構(gòu)造動(dòng)畫(huà),其實(shí)語(yǔ)言無(wú)所謂,重在原理。
@for $i from 1 through 100 { .animation[data-animation-position='#{$i}'] { left: #{$i}vw; } }
這里運(yùn)用
sass
的循環(huán)函數(shù)來(lái)創(chuàng)造1到100的匹配
class
名為
animation
和屬性選擇器為
[data-animation-position=1~100vw]
的值,例如我們想要元素的
left
為
50vw
,就直接添加
class
名
data-animation-position=50vw
。這里有兩點(diǎn)需要說(shuō)明:
vw
:注意單位是
vw
,我們想要雪花的起始點(diǎn)出現(xiàn)在水平方向的任意位置,而
vw
是把屏幕等分為
100
份,
100vw
就是滿屏;$timing: ( linear: linear, ease: ease, ease-in: ease-in, ease-out: ease-out, ease-in-out: ease-in-out ); @each $key, $value in $timing { .animation[data-animation-timing='#{$key}'] { transition-timing-function: $value; } }
時(shí)間包含動(dòng)畫(huà)運(yùn)動(dòng)時(shí)間和延時(shí)時(shí)間。
@for $i from 1 through 4 { .animation[data-animation-delay='#{$i}'] { animation-delay: #{$i}s; } } @for $i from 4 through 8 { .animation[data-animation-duration='#{$i}'] { animation-duration: #{$i}s; } }
下雪由兩個(gè)動(dòng)畫(huà)組成,分別是下落
fall
和搖擺
swing
,下落的動(dòng)畫(huà)是固定的,只有搖擺需要隨機(jī),所以我自定義了屬性匹配規(guī)則,就可以隨機(jī)搖擺了。
@for $i from 1 through 4 { .animation[data-animation-name='#{$i}'] { animation-name: fall, swing#{$i}; } } @for $i from 1 through 4 { @keyframes swing#{$i}{ 25% { transform: translateX(-#{$i * 10}px); } 50% { transform: translateX(#{$i * 10}px); } 75%{ transform: translateX(-#{$i * 10}px); } 100%{ transform: translateX(#{$i * 10}px); } } }
這里用
react
來(lái)演示代碼,還是那句話只要理解了原理,語(yǔ)言其實(shí)并不太重要。
{ Array(10).fill().map((v, i) => ( )) }
我們的雪花元素包含幾下幾個(gè)屬性值:
data-animation-position
:起始位;
data-animation-timing
:下雪速度;
data-animation-delay
:延時(shí);
data-animation-duration
:下雪總時(shí)間;
data-animation-name
:下落動(dòng)畫(huà)和搖擺動(dòng)畫(huà)。random(min, max){ return Math.floor(Math.random() * (max - min + 1) + min) }
position(){ return this.random(1, 100) } delay(){ return this.random(1, 4) } duration(){ return this.random(4, 8) } name(){ return this.random(1, 4) } timing(){ return ['linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out'][this.random(0, 4)] }
自己是個(gè)做了幾年全棧開(kāi)發(fā)的老碼農(nóng),如果你對(duì)前端開(kāi)發(fā)這門(mén)技術(shù)感興趣,這里推薦一下我的前端學(xué)習(xí)交流群: 767273102 ,里面都是學(xué)習(xí)前端的從最基礎(chǔ)的HTML+CSS+JavaScript。jQuery,Ajax,node,angular等到移動(dòng)端HTML5的項(xiàng)目實(shí)戰(zhàn)的資料都有整理,送給每一位前端小伙伴。最新技術(shù),與企業(yè)需求同步。好友都在里面學(xué)習(xí)交流,每天都會(huì)有大牛定時(shí)講解前端技術(shù)!