目录
5、调用requestAnimationFrame启动动画,使粒子移动起来
11、通过与鼠标的距离和相对位置进行计算来重新给粒子添加速度
闲聊
一年前觉得别人写的贼酷贼神奇的canvas粒子动画背景,一年后自己写了一个更nb的,hahahaha!
好吧,其实也没啥难的,前后大概花了俩小时,只不过是最近才正儿八经学了一下canvas,写个东西来练练手。
言归正传,这个粒子背景的粒子移动和粒子直接的连线以及和鼠标的连线都很简单,两个难点在于鼠标跟随和点击散开,下面的介绍中我将重点说一下这两个功能点。
看下效果

没有鼠标?截图给隐藏掉了,位置就不用我说了吧。

gif好糊啊= =
先贴下代码吧
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Starry</title>
</head>
<body>
<div style="position: fixed;top: 0;left:0;bottom: 0;right: 0;z-index: 0">
<canvas id="canvas" style="background-color: rgb(50,64,87);"></canvas>
</div>
<script type="text/javascript">
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
let width = window.innerWidth
let height = window.innerHeight
let dotsNum = 80 // 点的数量
let radius = 1 // 圆的半径,连接线宽度的一半
let fillStyle = 'rgba(255,255,255,0.5)' // 点的颜色
let lineWidth = radius * 2
let connection = 120 // 连线最大距离
let followLength = 80 // 鼠标跟随距离
let dots = []
let animationFrame = null
let mouseX = null
let mouseY = null
function addCanvasSize () { // 改变画布尺寸
width = window.innerWidth
height = window.innerHeight
canvas.width = width
canvas.height = height
ctx.clearRect(0, 0, width, height)
dots = []
if (animationFrame) window.cancelAnimationFrame(animationFrame)
initDots(dotsNum)
moveDots()
}
function mouseMove (e) {
mouseX = e.clientX
mouseY = e.clientY
}
function mouseOut (e) {
mouseX = null
mouseY = null
}
function mouseClick () {
for (const dot of dots) dot.elastic()
}
class Dot {
constructor(x, y) {
this.x = x
this.y = y
this.speedX = Math.random() * 2 - 1
this.speedY = Math.random() * 2 - 1
this.follow = false
}
draw () {
ctx.beginPath()
ctx.arc(this.x, this.y, radius, 0, 2 * Math.PI)
ctx.fill()
ctx.closePath()
}
move () {
if (this.x >= width || this.x <= 0) this.speedX = -this.speedX
if (this.y >= height || this.y <= 0) this.speedY = -this.speedY
this.x += this.speedX
this.y += this.speedY
if (this.speedX >= 1) this.speedX--
if (this.speedX <= -1) this.speedX++
if (this.speedY >= 1) this.speedY--
if (this.speedY <= -1) this.speedY++
this.correct()
this.connectMouse()
this.draw()
}
correct () { // 根据鼠标的位置修正
if (!mouseX || !mouseY) return
let lengthX = mouseX - this.x
let lengthY = mouseY - this.y
const distance = Math.sqrt(lengthX ** 2 + lengthY ** 2)
if (distance <= followLength) this.follow = true
else if (this.follow === true && distance > followLength && distance <= followLength + 8) {
let proportion = followLength / distance
lengthX *= proportion
lengthY *= proportion
this.x = mouseX - lengthX
this.y = mouseY - lengthY
} else this.follow = false
}
connectMouse () { // 点与鼠标连线
if (mouseX && mouseY) {
let lengthX = mouseX - this.x
let lengthY = mouseY - this.y
const distance = Math.sqrt(lengthX ** 2 + lengthY ** 2)
if (distance <= connection) {
opacity = (1 - distance / connection) * 0.5
ctx.strokeStyle = `rgba(255,255,255,${opacity})`
ctx.beginPath()
ctx.moveTo(this.x, this.y)
ctx.lineTo(mouseX, mouseY);
ctx.stroke();
ctx.closePath()
}
}
}
elastic () { // 鼠标点击后的弹射
let lengthX = mouseX - this.x
let lengthY = mouseY - this.y
const distance = Math.sqrt(lengthX ** 2 + lengthY ** 2)
if (distance >= connection) return
const rate = 1 - distance / connection // 距离越小此值约接近1
this.speedX = 40 * rate * -lengthX / distance
this.speedY = 40 * rate * -lengthY / distance
}
}
function initDots (num) { // 初始化粒子
ctx.fillStyle = fillStyle
ctx.lin

本文详细介绍了一款基于canvas的互动粒子动画的实现过程,包括粒子移动、鼠标跟随、点击散开等功能,以及代码细节。
&spm=1001.2101.3001.5002&articleId=105995732&d=1&t=3&u=ed6a53147f594b33b09a170813440b88)
2617

被折叠的 条评论
为什么被折叠?



