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