用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)