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

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

因?yàn)槿粘1蝗苏f(shuō)博客沒(méi)文章所以就算只是寫了個(gè)很簡(jiǎn)單的小星星也努力的把過(guò)程拼湊出來(lái)寫個(gè)博客辣?。?。


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用來(lái)指定頁(yè)面上最多能同時(shí)存在幾個(gè)星星
  • newStar用來(lái)指定同時(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上啦!
如果有人想要使用的話(雖然感覺(jué)并沒(méi)有人會(huì)用
可以先引入js文件
然后
// 傳入canvas的id,想要的canvas的大小
StarLight.init("canvas", screen.width, screen.height)
// 直接使用就好啦(??? ? ???)!
StarLight.star()
// 可以調(diào)用set來(lái)設(shè)置初始的星星個(gè)數(shù)及頁(yè)面上最大的個(gè)數(shù)和每次新生成的個(gè)數(shù)
StarLight.set (num, maxStar, newStar)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容