107 lines
2.6 KiB
Vue
107 lines
2.6 KiB
Vue
<template>
|
|
<div
|
|
id="background-canvas-wrapper"
|
|
class="w100 no-scroll overflow-hidden bg-base position-relative"
|
|
style="height: 100vh;"
|
|
>
|
|
<canvas id="canvas" class="absolute-top"/>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { onMounted, onUnmounted } from 'vue'
|
|
|
|
onMounted(() => {
|
|
const canvas = document.getElementById("canvas") as HTMLCanvasElement
|
|
const ctx = canvas.getContext("2d")!
|
|
const opts = {
|
|
pColor: "rgb(200,200,200)",
|
|
lRGB: "200,200,200",
|
|
amt: 20,
|
|
defS: 0.1,
|
|
varS: 1,
|
|
defR: 2,
|
|
varR: 2,
|
|
linkR2: 200 ** 2
|
|
}
|
|
|
|
let w: number, h: number, aid: number
|
|
const particles: Particle[] = []
|
|
|
|
const resize = () => {
|
|
w = canvas.width = window.innerWidth
|
|
h = canvas.height = window.innerHeight
|
|
}
|
|
|
|
class Particle {
|
|
x = Math.random() * w
|
|
y = Math.random() * h
|
|
s = opts.defS + Math.random() * opts.varS
|
|
a = Math.random() * Math.PI * 2
|
|
vx = Math.cos(this.a) * this.s
|
|
vy = Math.sin(this.a) * this.s
|
|
r = opts.defR + Math.random() * opts.varR
|
|
|
|
update() {
|
|
if (this.x + this.vx > w || this.x + this.vx < 0) this.vx *= -1
|
|
if (this.y + this.vy > h || this.y + this.vy < 0) this.vy *= -1
|
|
this.x += this.vx
|
|
this.y += this.vy
|
|
ctx.beginPath()
|
|
ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2)
|
|
ctx.fillStyle = opts.pColor
|
|
ctx.fill()
|
|
}
|
|
}
|
|
|
|
resize()
|
|
for (let i = 0; i < opts.amt; i++) particles.push(new Particle())
|
|
|
|
const loop = () => {
|
|
ctx.clearRect(0, 0, w, h)
|
|
particles.forEach(p => p.update())
|
|
|
|
for (let i = 0; i < particles.length; i++) {
|
|
const p1 = particles[i]
|
|
for (let j = i + 1; j < particles.length; j++) {
|
|
const p2 = particles[j]
|
|
if (!p1 || !p2) continue
|
|
|
|
const dx = p1.x - p2.x
|
|
const dy = p1.y - p2.y
|
|
const d2 = dx * dx + dy * dy
|
|
if (d2 < opts.linkR2) {
|
|
ctx.strokeStyle = `rgba(${opts.lRGB}, ${1 - d2 / opts.linkR2})`
|
|
ctx.lineWidth = 0.5
|
|
ctx.beginPath()
|
|
ctx.moveTo(p1.x, p1.y)
|
|
ctx.lineTo(p2.x, p2.y)
|
|
ctx.stroke()
|
|
}
|
|
}
|
|
}
|
|
aid = requestAnimationFrame(loop)
|
|
}
|
|
|
|
window.addEventListener("resize", resize)
|
|
loop()
|
|
|
|
onUnmounted(() => {
|
|
window.removeEventListener("resize", resize)
|
|
cancelAnimationFrame(aid)
|
|
})
|
|
})
|
|
</script>
|
|
|
|
<style>
|
|
#background-canvas-wrapper {
|
|
position: absolute !important;
|
|
display: block;
|
|
top: 0;
|
|
left: 0;
|
|
z-index: -1;
|
|
margin: 0;
|
|
height: 100vh !important;
|
|
}
|
|
</style>
|