Draw ripples on mousemove as well

This commit is contained in:
arne 2024-01-27 09:47:37 +01:00
commit 398aa43338
9 changed files with 36 additions and 11 deletions

View file

View file

@ -4,6 +4,7 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ripples | compost.party</title>
<link rel="stylesheet" href="/src/style.css" type="text/css" media="screen" />
</head>
<body>
<canvas id="canvas"></canvas>

View file

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Before After
Before After

View file

@ -1,20 +1,22 @@
import './style.css'
const canvas = document.querySelector<HTMLCanvasElement>('#canvas')!
const ctx = canvas.getContext('2d')!
const MIN_RADIUS = 20
const MAX_RADIUS = 200
const MAX_AGE = 5000 // in milliseconds
const MAX_AGE = 1000 // in milliseconds
type Point = [number, number]
type Particle = {
position: [number, number],
position: Point
age: number
maxRadius: number
}
const createParticle = (x: number, y: number): Particle => ({
position: [x, y],
const createParticle = (position: [number, number], maxRadius: number): Particle => ({
position,
maxRadius,
age: 0,
})
@ -24,12 +26,35 @@ let state = {
type State = typeof state
canvas.addEventListener('click', (e) => {
canvas.addEventListener('mousedown', (e) => {
// TODO Normalize x and y coords
const particle = createParticle(e.clientX, e.clientY)
const particle = createParticle([e.clientX, e.clientY], MAX_RADIUS)
state.particles.push(particle)
})
function* minDist(dist: number) {
let prev: Point
while (true) {
yield (cur: Point) => {
if (prev == null || Math.sqrt(Math.pow(prev[0]-cur[0], 2) + Math.pow(prev[1]-cur[1], 2)) >= dist) {
prev = cur
return true
}
return false
}
}
}
const hasSpace = minDist(70)
canvas.addEventListener('mousemove', (e) => {
const shouldSpawn = hasSpace.next().value!
if (shouldSpawn([e.clientX, e.clientY])) {
const particle = createParticle([e.clientX, e.clientY], MAX_RADIUS / 3*2)
state.particles.push(particle)
}
})
const update = (state: State, deltaTime: number): State => ({
particles: state.particles
.map(p => ({
@ -44,12 +69,12 @@ const render = (state: State, ctx: CanvasRenderingContext2D) => {
for (const particle of state.particles) {
const progress = (particle.age / MAX_AGE)
const opacity = Math.min(1, (1-progress)*(1-progress))
const opacity = Math.min(1, Math.pow(1-progress, 3)) * (particle.maxRadius / MAX_RADIUS)
ctx.beginPath()
ctx.strokeStyle = `rgba(40, 40, 40, ${opacity})`
const [x, y] = particle.position
const radius = (progress * (MAX_RADIUS - MIN_RADIUS)) + MIN_RADIUS
const radius = (progress * (particle.maxRadius - MIN_RADIUS)) + MIN_RADIUS
ctx.ellipse(x, y, radius, radius, 0, 0, Math.PI * 2)
ctx.stroke()
}

View file

@ -7,5 +7,4 @@ body {
}
canvas {
}