新主题的背景在大屏状态下是属于有点单调一点,单栏的情况下结合短宽的情况下看起是空旷了些,想着给后面加一个背景,暂时没想好怎么换,不过夜间模式的情况下还是,想弄出一点不一样的效果,于是想到星光的闪烁的画面,觉得是不错的思路,刚好看到有一位 博主Jdeal 的站点也有类似的效果,想做差不多就可以了,看了一下源码是用多个 div
生成的效果,再加上 css
配合颜色和动画,这样做虽然可以,但是会有很多无效元素在页面上,我的强迫症还是决定用 canvas
重写一个,所有动画都在里面执行,需要注意的几点如下:
- 随机生成大小不超过3像素的圆点,随机透明度,随机位置。
- 圆点整体向上运动,速度随机,角度随机。
- 移动的过程中有圆点的透明度会持续衰弱为0
大致就是如下效果。
根据需求,下面开始写代码。
创建 Canvas 元素并获取上下文
var canvas = document.getElementById('myCanvas')
var ctx = canvas.getContext('2d')
设置 Canvas 的宽度和高度
canvas.width = window.innerWidth
canvas.height = window.innerHeight
// 创建一个包含萤火光点信息的数组
var sparks = []
生成圆点
function createSpark() {
const x = Math.random() * canvas.width
const y = Math.random() * canvas.height // 从底部开始
const radius = Math.random() * 1 + 1
const opacity = Math.random() * .5 + .5
sparks.push({
x: x,
y: y,
radius: radius,
opacity: opacity,
blinkCount: 0,
speedX: (Math.random() - .5) * 2,
speedY: -Math.random() * .1 - .5, // 向上移动,上升速度减小
angle: Math.random() * Math.PI * 2, // 初始角度随机
angularSpeed: Math.random() * .1 - .05 // 角速度随机增大
})
}
更新圆点的位置,并绘制到 Canvas 上
function updateSparks() {
for (let i = 0; i < sparks.length; i++) {
const spark = sparks[i]
spark.x += spark.speedX
spark.y += spark.speedY
spark.angle += spark.angularSpeed
// 左右摆动效果
spark.x += Math.sin(spark.angle) * .1
if (spark.opacity <= 0) {
sparks.splice(i, 1)
i--
continue
}
spark.opacity -= 0.01;
ctx.beginPath()
ctx.arc(spark.x, spark.y, spark.radius, 0, Math.PI * 2)
ctx.fillStyle = `rgba(255, 255, 255, ${spark.opacity})`
ctx.fill()
}
}
使用 requestAnimationFrame 实现动画效果
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height)
if (sparks.length < 10) {
createSpark()
}
updateSparks()
requestAnimationFrame(animate)
}
// 启动动画
animate()
大功告成,可以效果可以看一下本站的夜间模式效果,虽然丑了点(又不是不能用!)