盒子
盒子
Posts List
  1. 用canvas实现简单的星空效果
    1. Step.0
    2. Step.1
    3. Step.2
    4. Step.3
    5. Step.4
    6. Step.5
    7. Finished!

用canvas实现简单的星空效果

用canvas实现简单的星空效果

因为日常被人说博客没文章所以就算只是写了个很简单的小星星也努力的把过程拼凑出来写个博客辣!(。


Step.0

涉及到的所有的代码都放在了我的github
首先看一下最终的效果图,可以参考我的博客首页或者下面这张图

Step.1

第一步当然是用canvas画个小星星啦✨

1
2
3
4
5
6
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)
}

画星星实际上是需要十个顶点,一个是外圈的五个顶点,用R指定,一个是内圈的五个顶点,用r指定,x和y则是圆心坐标

Step.2

确定整个星空的组成部分

1
2
3
4
5
6
7
8
9
10
const setting = {
width: screen.width,
height: screen.height,
canvas: null,
content: null,
maxStar: 100,
newStar: 6,
starArr: [],
number: 100
}

  • width和height用于指定canvas的大小,以及为之后的随机生成星星的位置做准备
  • maxStar用来指定页面上最多能同时存在几个星星
  • newStar用来指定同时新生成几个星星
  • starArr用于存放星星
  • number用于指定初始星星的个数

Step.3

初始化canvas画布

1
2
3
4
5
6
7
8
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")
}

生成一百个随机坐标并push到starArr数组中

1
2
3
4
5
6
7
8
9
10
11
12
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),
// 用于指定星星的颜色,因为我设置了一个颜色数组,有8种配色方案,为了使效果更为美观
deg: Math.random()*6*minus,
scale: 3+Math.random()*3,
alpha: 0.5+Math.random()*0.1 // 透明度
})
}

Step.4

用requestAnimationFrame刷新星星的移动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
function updateStar() {
setting.content.clearRect(0, 0, setting.width, setting.height) //清除画布
setting.content.save() //save与restore对应
// 更改x,y坐标
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
// 若星星超出屏幕范围,则从数组中删去
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();
// 设置透明度、阴影、颜色等
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

星星超出屏幕范围后从星星数组中删除,并且要每隔一段时间重新生成星星

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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上啦!
如果有人想要使用的话(虽然感觉并没有人会用
可以先引入js文件
然后
// 传入canvas的id,想要的canvas的大小
StarLight.init(“canvas”, screen.width, screen.height)
// 直接使用就好啦(๑•́ ∀ •̀๑)!
StarLight.star()
// 可以调用set来设置初始的星星个数及页面上最大的个数和每次新生成的个数
StarLight.set (num, maxStar, newStar)