用canvas實(shí)現(xiàn)簡(jiǎn)單的星空效果

用canvas實(shí)現(xiàn)簡(jiǎn)單的星空效果

因?yàn)槿粘1蝗苏f博客沒文章所以就算只是寫了個(gè)很簡(jiǎn)單的小星星也努力的把過程拼湊出來寫個(gè)博客辣M┨馈(鱼鸠。


Step.0

涉及到的所有的代碼都放在了我的github
首先看一下最終的效果圖间涵,可以參考我的博客首頁(yè)或者下面這張圖

image

Step.1

第一步當(dāng)然是用canvas畫個(gè)小星星啦?

for (let i = 0; i < 5; i++) {
content.lineTo(Math.cos((18+j*72)/180*Math.PI)*R+x,
-Math.sin((18+j*72)/180*Math.PI)*R+y)
content.lineTo(Math.cos((54+j*72)/180*Math.PI)*r+x,
-Math.sin((54+j*72)/180*Math.PI)*r+y)
}

畫星星實(shí)際上是需要十個(gè)頂點(diǎn)南窗,一個(gè)是外圈的五個(gè)頂點(diǎn)礁阁,用R指定护桦,一個(gè)是內(nèi)圈的五個(gè)頂點(diǎn)含衔,用r指定,x和y則是圓心坐標(biāo)

Step.2

確定整個(gè)星空的組成部分

const setting = {
width: screen.width,
height: screen.height,
canvas: null,
content: null,
maxStar: 100,
newStar: 6,
starArr: [],
number: 100
}
  • width和height用于指定canvas的大小二庵,以及為之后的隨機(jī)生成星星的位置做準(zhǔn)備
  • maxStar用來指定頁(yè)面上最多能同時(shí)存在幾個(gè)星星
  • newStar用來指定同時(shí)新生成幾個(gè)星星
  • starArr用于存放星星
  • number用于指定初始星星的個(gè)數(shù)

Step.3

初始化canvas畫布

function init (canvas, w, h) {
setting.canvas = document.getElementById(canvas)
setting.canvas.setAttribute("width", w)
setting.canvas.setAttribute("height", h)
setting.width = w
setting.height = h
setting.content = setting.canvas.getContext("2d")
}

生成一百個(gè)隨機(jī)坐標(biāo)并push到starArr數(shù)組中

for (let i = 0; i < setting.number; i++) {
let minus = Math.random() < 0.5?-1:1;
setting.starArr.push({
x: Math.random()*setting.width,
y: Math.random()*setting.height,
c: Math.floor(Math.random()*6),
// 用于指定星星的顏色贪染,因?yàn)槲以O(shè)置了一個(gè)顏色數(shù)組,有8種配色方案催享,為了使效果更為美觀
deg: Math.random()*6*minus,
scale: 3+Math.random()*3,
alpha: 0.5+Math.random()*0.1 // 透明度
})
}

Step.4

用requestAnimationFrame刷新星星的移動(dòng)

function updateStar() {
setting.content.clearRect(0, 0, setting.width, setting.height) //清除畫布
setting.content.save() //save與restore對(duì)應(yīng)

// 更改x,y坐標(biāo)
for (let i = 0; i < setting.starArr.length; i++) {
let h = 0.35*setting.starArr[i].scale
setting.starArr[i].x += Math.tan(setting.starArr[i].deg*Math.PI/180)*h/2
setting.starArr[i].y = setting.starArr[i].y + h

// 若星星超出屏幕范圍杭隙,則從數(shù)組中刪去 
if (setting.starArr[i].x < 0 || setting.starArr[i].x > setting.width || setting.starArr[i].y > setting.height) {
setting.starArr.splice(i--, 1)
continue;
}

// 重繪星星
setting.content.beginPath()
for (var j = 0; j < 5; j++) {
setting.content.lineTo(Math.cos((18+j*72)/180*Math.PI)*10+setting.starArr[i].x,
-Math.sin((18+j*72)/180*Math.PI)*10+setting.starArr[i].y)
setting.content.lineTo(Math.cos((54+j*72)/180*Math.PI)*5+setting.starArr[i].x,
-Math.sin((54+j*72)/180*Math.PI)*5+setting.starArr[i].y)
}
setting.content.closePath();

// 設(shè)置透明度、陰影因妙、顏色等
setting.content.globalAlpha = setting.starArr[i].alpha
setting.content.shadowOffsetX = 2
setting.content.shadowOffsetY = 2
setting.content.shadowBlur = 4
setting.content.shadowColor = "rgba(0, 0, 0, 0.15)"
setting.content.fillStyle = color[setting.starArr[i].c]
setting.content.fill()
}
setting.content.restore()
window.requestAnimationFrame(updateStar)
}

Step.5

星星超出屏幕范圍后從星星數(shù)組中刪除痰憎,并且要每隔一段時(shí)間重新生成星星

function createNewStar() {
setTimeout(function() {
if (setting.starArr.length < setting.maxStar) {
for (let i = 0; i < setting.newStar; i++) {
let minus = Math.random() < 0.5?-1:1;
setting.starArr.push({
x: Math.random()*setting.width,
y: 0,
c: Math.floor(Math.random()*6),
deg: Math.random()*6*minus,
scale: 3+Math.random()*3,
alpha: 0.5+Math.random()*0.1
})
}
}
createNewStar()
}, Math.random()*200 + 500)
}

Finished!

完工啦(o′ω`o)!
我把自己寫的那份放到github上啦攀涵!
如果有人想要使用的話(雖然感覺并沒有人會(huì)用
可以先引入js文件
然后
// 傳入canvas的id铣耘,想要的canvas的大小
StarLight.init("canvas", screen.width, screen.height)
// 直接使用就好啦(??? ? ???)!
StarLight.star()
// 可以調(diào)用set來設(shè)置初始的星星個(gè)數(shù)及頁(yè)面上最大的個(gè)數(shù)和每次新生成的個(gè)數(shù)
StarLight.set (num, maxStar, newStar)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末以故,一起剝皮案震驚了整個(gè)濱河市蜗细,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌怒详,老刑警劉巖炉媒,帶你破解...
    沈念sama閱讀 222,865評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異昆烁,居然都是意外死亡吊骤,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門静尼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來白粉,“玉大人,你說我怎么就攤上這事鼠渺∥显” “怎么了?”我有些...
    開封第一講書人閱讀 169,631評(píng)論 0 364
  • 文/不壞的土叔 我叫張陵系冗,是天一觀的道長(zhǎng)奕扣。 經(jīng)常有香客問我,道長(zhǎng)掌敬,這世上最難降的妖魔是什么惯豆? 我笑而不...
    開封第一講書人閱讀 60,199評(píng)論 1 300
  • 正文 為了忘掉前任池磁,我火速辦了婚禮,結(jié)果婚禮上楷兽,老公的妹妹穿的比我還像新娘地熄。我一直安慰自己,他們只是感情好芯杀,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,196評(píng)論 6 398
  • 文/花漫 我一把揭開白布端考。 她就那樣靜靜地躺著,像睡著了一般揭厚。 火紅的嫁衣襯著肌膚如雪却特。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,793評(píng)論 1 314
  • 那天筛圆,我揣著相機(jī)與錄音裂明,去河邊找鬼。 笑死太援,一個(gè)胖子當(dāng)著我的面吹牛闽晦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播提岔,決...
    沈念sama閱讀 41,221評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼仙蛉,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了碱蒙?” 一聲冷哼從身側(cè)響起荠瘪,我...
    開封第一講書人閱讀 40,174評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎振亮,沒想到半個(gè)月后巧还,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鞭莽,經(jīng)...
    沈念sama閱讀 46,699評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡坊秸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,770評(píng)論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了澎怒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片褒搔。...
    茶點(diǎn)故事閱讀 40,918評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖喷面,靈堂內(nèi)的尸體忽然破棺而出星瘾,到底是詐尸還是另有隱情,我是刑警寧澤惧辈,帶...
    沈念sama閱讀 36,573評(píng)論 5 351
  • 正文 年R本政府宣布琳状,位于F島的核電站,受9級(jí)特大地震影響盒齿,放射性物質(zhì)發(fā)生泄漏念逞。R本人自食惡果不足惜困食,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,255評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望翎承。 院中可真熱鬧硕盹,春花似錦、人聲如沸叨咖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)甸各。三九已至垛贤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間痴晦,已是汗流浹背南吮。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留誊酌,地道東北人部凑。 一個(gè)月前我還...
    沈念sama閱讀 49,364評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像碧浊,于是被迫代替她去往敵國(guó)和親涂邀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,926評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容