canvas 动画
2024-05-10 23:42:41
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
const canvas = ref<HTMLCanvasElement>()
function getRandom(min: number, max: number) {
return Math.floor(Math.random() * (max - min + 1) + min)
}
onMounted(() => {
const ctx = canvas.value?.getContext('2d')
class Point {
constructor() {
this.r = 4
this.x = getRandom(0, canvas.value.width - this.r / 2)
this.y = getRandom(0, canvas.value.height - this.r / 2)
this.xSpeed = getRandom(-50, 50)
this.ySpeed = getRandom(-50, 50)
this.lastMoveTime = null
}
x: number
y: number
r: number
xSpeed: number
ySpeed: number
lastMoveTime: number | null
draw() {
if (this.lastMoveTime) {
const time = (Date.now() - this.lastMoveTime) / 1000
this.x = this.x + this.xSpeed * time
this.y = this.y + this.ySpeed * time
// 边界检测
if (this.x < 0 || this.x > canvas.value.width - this.r) {
this.xSpeed = -this.xSpeed
}
if (this.y < 0 || this.y > canvas.value.height - this.r) {
this.ySpeed = -this.ySpeed
}
}
ctx?.beginPath()
ctx?.arc(this.x, this.y, this.r, 0, Math.PI * 2)
ctx!.fillStyle = 'rgb(200, 200, 200)'
ctx?.fill()
this.lastMoveTime = Date.now()
}
}
class Graph {
constructor(pointNumber = 15, maxDistance = 200) {
this.points = new Array(pointNumber).fill(0).map(() => new Point())
this.maxDistance = maxDistance
}
points: Point[]
maxDistance: number
draw() {
if (!canvas) return
requestAnimationFrame(() => {
this.draw()
})
// 每次移动前清空画布
ctx?.clearRect(0, 0, canvas.value.width, canvas.value.height)
const length = this.points.length
for (let i = 0; i < length; i++) {
this.points[i].draw()
for (let j = i + 1; j < length; j++) {
const distance = Math.sqrt(
Math.pow(this.points[i].x - this.points[j].x, 2) +
Math.pow(this.points[i].y - this.points[j].y, 2),
)
if (distance < this.maxDistance) {
ctx?.beginPath()
ctx?.moveTo(this.points[i].x, this.points[i].y)
ctx?.lineTo(this.points[j].x, this.points[j].y)
ctx?.closePath()
// 线的透明度随距离变化
ctx!.strokeStyle = `rgba(200, 200, 200, ${
1 - distance / this.maxDistance
})`
ctx?.stroke()
}
}
}
}
}
// 初始化
function init() {
if (!canvas) return
canvas.value.width = 650
canvas.value.height = 550
canvas.value.style.border = '1px solid rgba(200, 200, 200)'
}
init()
const graph = new Graph()
graph.draw()
})
</script>
<template>
<div>
<canvas ref="canvas" />
</div>
</template>