我用 140 行代碼,帶你看一場流星雨?

📣 大家好,我叫小丞同學,今天走個治愈風,來做一個治愈系的流星雨效果
前言
在一個夜深人靜的晚上,程式員小丞坐在屋頂上,看著螢屏上滿屏的error,心里拔涼拔涼的,淚水潤濕了臉龐,無數個自己提桶跑路的身影充斥在腦海之中,猛然才發現自己還沒有桶,此時星空中閃過了漫天的流星,小丞看到此景,心中的bug早已化去,留下的是還原此景的豪言壯舉!(夢醒了,純屬瞎編)
小丞把腦海中的場景描繪成了影片,開始了他的 show time

分析影片
產品的需求已經明確下來了,很簡單實作一個流星雨效果,那么接下來我們需要對影片進行分析,然后一步步的實作最終的效果,第一次看到這個效果的時候感覺很震撼,流星的效果非常的逼真,很炫酷,我們來分析一下程序,從一般的思路來看,我們可以通過 CSS3 影片來實作,繪制一個流星,讓它從右上向左下移動,流星滑動的起點和終點都在可視框之外,這樣就能營造一種遠端飛來的效果,同時實作影片的回圈,

前處理器選擇
那么這么多的流星個體,我們需要怎么實作呢,你能想到幾種方式?
第一種:采用 JS 動態插入 html
第二種:采用 canvas 畫布,通過實體化的方式創建粒子
第三種:純HTML
我當然選擇的是最簡單的純HTML啦,通過編譯器的element 語法快速生成 50個 div標簽(.star*50)這香,免去了考慮JS操作的性能問題,以及采用canvas畫布帶來的兼容性問題,
從小丞提供的影片來看,每個流星它的劃動速度,它的間隔時間,起始的位置甚至是長度都是不一樣的,那么對于這么多的元素,難道我們需要給他們一個個撰寫 CSS 代碼嗎,答案當然是是的,當然我們不會采用 css 來開發,我們可以選擇CSS前處理器來開發,采用less和sass語法上存在的差異,同時sass的功能比less更加的強大,起初我準備采用less進行產品的開發,但是遇到了這樣的問題:
在設定流星長度等屬性中,需要采用random來生成亂數,但是在less的官方檔案中發現,并沒有內置random的 API

在查閱了資料后,發現了由于less是由JS撰寫的,所以它天然的支持JS語法,需要在前面加上~符號,因此嘗試用JS內置物件Math來呼叫生成亂數,結果出現了編譯報錯的情況,但是在網上的less轉化工具中能正確轉化,有點不解…(詭異)

但是我們可以清晰的在sass的官方檔案上看到random的身影,這樣就沒有這么多怪事了,本次的產品確認采用sass前處理器進行代碼撰寫

產品制作
確定了使用的開發工具,我們就可以正式的來撰寫代碼了
1. 確定流星移動方向
從影片來看,流星的移動方向是一定的,我們可以通過給流星添加一個影片,然后將整個裝流星粒子的容器旋轉一定的角度,這樣流星的移動方向就會是一定方向上的
.container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 70%;
transform: rotate(-25deg);
}

藍色方塊的縱向方向就是流星移動的方向
確定了流星的移動方向,接下來我們來繪制流星樣式
2. 繪制流星樣式
流星的效果通過兩部分來組成,一個是拖尾,一個是星星
首先拖尾的效果,可以通過漸變來實作
background: linear-gradient(45deg, currentColor, transparent);
filter: drop-shadow(0 0 6px currentColor);
這里采用了一個currentColor表示的是當前字體的顏色,這是一個變數,可以直接使用,這樣的好處是在改變color值時拖尾的顏色和陰影的顏色就會直接改變,不用去單獨改變兩個值

關于陰影的處理,大多數采用的都是box-shadow,以致于drop-shadow很少人知道,它和box-shadow有著怎樣的區別呢?
box-shadow簡單翻譯一下“盒陰影”,是css3中新增的屬性,用于增加邊框陰影,讓原有的元素變得更多樣性,有四個引數,第一個控制水平方向偏移,第二個控制垂直方向偏移,第三個控制模糊度,第四個控制陰影顏色,
drop-shadow也是用于投影,但是它不局限于矩形區域,
drop-shadow符合真實世界的投影,非透明的顏色就有投影,透明的就沒有投影,而box-shadow只是盒子投影,即使盒子區域內有透明區域,也會投影

上圖(來源網路,侵刪)就展示了兩者間顯著的區別,在很多場景drop-shadow很實用啊!!
流星頭部星星的效果
用雙偽元素,繪制兩個兩頭細小的短線,定位到頭部,旋轉一定角度,實作閃亮星星效果
.star::before {
transform: rotate(45deg);
}
.star::after {
transform: rotate(-45deg);
}

3. 添加劃動影片
對于單個流星的滑動影片非常簡單,只需要改變一下位置就可以了,在開始的時候調整transformX的值將流星移出可視區外
// 給單個流星添加animation以及transform屬性
transform: translate3d(220vh, 0, 0);
animation: fall 10s linear infinite;
// 影片宣告
@keyframes fall {
to {
transform: translate3d(-30em, 0, 0);
}
}
但是我們需要操作的是全部的粒子,每個粒子都要隨機時間,遠不止這么簡單,繼續向下看
4. 回圈設定樣式
由于每個流星的影片延時,影片時間等屬性是在一定范圍內的亂數,因此需要通過回圈來設定樣式
首先需要先在css中撰寫一個能回傳在一定范圍內的亂數函式
@function random_range($min, $max) {
$rand: random();
$random_range: $min + floor($rand * (($max - $min) + 1));
@return $random_range;
}
這個方法接收兩個引數,左邊界和有邊界,通過scss中自帶的random方法獲取一個亂數,然后乘以兩個邊界的差值,再加上左邊界,這樣就能實作需求
對于scss中撰寫函式,需要特別注意它的語法
在呼叫函式的時候通過random_range(0vh, 10000vh)來獲取,在使用的時候可以這樣:
--star-length:#{random_range(500em, 750em) / 100};
接下來給每個流星設定隨機樣式
@for $i from 1 through $star-count {
&:nth-child(#{$i}) {
--star-length:#{random_range(500em, 750em) / 100};
--top-offset: #{random_range(0vh, 10000vh) / 100};
--fall-duration: #{random_range(6000, 12000s) / 1000};
--fall-delay: #{random_range(0, 10000s) / 1000};
}
}
在.star的樣式代碼內,撰寫一個回圈,star-count是在前面定義的一個長度變數為50這樣回圈遍歷i會從0遞增到50,這樣就能通過nth-child(i)來給50流星粒子添加樣式
scss回圈代碼轉化后

這樣每個流星元素就能有獨立的隨機的屬于自己的樣式,從而實作隨機的效果
5. 系結影片
animation: fall var(--fall-duration) var(--fall-delay) linear infinite;
將之前個流星粒子添加的animation樣式更改為自己的影片時間和延時時間

6. 添加背景
最后加上一個符合場景的絕美的背景,接下來讓我陪你們看一場流星雨吧!

總結
通過這篇文章我們學到了什么呢?
scss函式scss回圈設定樣式box-shadow和drop-shadow的區別- 偽元素的妙用
- 拖尾效果的實作
完整 scss 代碼
html代碼只需要在body中輸入.container>.star*50回車即可
/* 設定背景 */
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background: url(starBgc.jpg);/* 背景圖 */
background-size: cover;
}
.container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 70%;
transform: rotate(-25deg);
}
// 生成范圍內亂數函式
@function random_range($min, $max) {
$rand: random();
$random_range: $min + floor($rand * (($max - $min) + 1));
@return $random_range;
}
.star {
$star-count: 50;
--star-height: 2px;
--star-width: calc(var(--star-length) / 6);
position: absolute;
/* 后面給每個星星都添加一個 */
top: var(--top-offset);
left: 0;
/* 設定每個星星的長寬 */
width: var(--star-length);
height: var(--star-height);
color: #fff;
background: linear-gradient(45deg, currentColor, transparent);
border-radius: 50%;
/* drop-shadow和box-shadow的區別 */
filter: drop-shadow(0 0 6px currentColor);
/*簡寫xyz */
transform: translate3d(220vh, 0, 0);
animation: fall var(--fall-duration) var(--fall-delay) linear infinite;
// 回圈
@for $i from 1 through $star-count {
&:nth-child(#{$i}) {
--star-length:#{random_range(500em, 750em)/100};
--top-offset: #{random_range(0vh, 10000vh) / 100};
--fall-duration: #{random_range(6000, 12000s) / 1000};
--fall-delay: #{random_range(0, 10000s) / 1000};
}
}
// 偽元素制作星星
&::before,
&::after {
position: absolute;
content: '';
top: 0;
left: calc(var(--star-width) / -2);
width: var(--star-width);
height: 100%;
background: linear-gradient(45deg, transparent, currentColor, transparent);
border-radius: inherit;
animation: blink 2s linear infinite;
}
&::before {
transform: rotate(45deg);
}
&::after {
transform: rotate(-45deg);
}
}
@keyframes fall {
to {
transform: translate3d(-30em, 0, 0);
}
}
@keyframes blink {
50% {
opacity: 0.6;
}
}
以上就是本文的全部內容了,希望你能喜歡💛,有什么問題可以評論區留言噢~
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/292391.html
標籤:其他
上一篇:2021華數杯數學建模B題思路
下一篇:淺談函式堆疊幀
