Skip to content

Commit

Permalink
Add a nice ripple effect on touch
Browse files Browse the repository at this point in the history
  • Loading branch information
crummy committed Aug 26, 2024
1 parent 0d8c829 commit 802ef03
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 7 deletions.
8 changes: 1 addition & 7 deletions src/components/Theremax.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Timer} from "./Timer.ts";
import type {Instrument} from "./player.ts";
import {getContext} from "svelte";
import {lerp} from "./lerp.ts";

interface Instant {
millis: number
Expand Down Expand Up @@ -31,12 +31,6 @@ class Recording {
}
}

function lerp(value: number, sourceRangeMin: number, sourceRangeMax: number, targetRangeMin: number, targetRangeMax: number) {
const targetRange = targetRangeMax - targetRangeMin;
const sourceRange = sourceRangeMax - sourceRangeMin;
return (value - sourceRangeMin) * targetRange / sourceRange + targetRangeMin;
}

export interface TheremaxVisualization {
clearLines(): void

Expand Down
63 changes: 63 additions & 0 deletions src/components/Visualization.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {Application, Graphics} from "pixi.js";
import type {TheremaxVisualization} from "./Theremax.ts";
import {lerp} from "./lerp.ts";

const screenPadding = 16;
const colours = [
Expand Down Expand Up @@ -38,6 +39,7 @@ export class Visualization implements TheremaxVisualization {
private columns: Graphics[] = []
private lines: Graphics[] = []
private progress = new Graphics();
private ripples = new Ripples()


async init(element: HTMLElement) {
Expand Down Expand Up @@ -71,7 +73,10 @@ export class Visualization implements TheremaxVisualization {
column.alpha *= 0.97;
}
this.tickListener(Date.now())
this.ripples.tick()
});

this.app.stage.addChild(this.ripples.graphics)
}

getWidth() {
Expand Down Expand Up @@ -136,6 +141,11 @@ export class Visualization implements TheremaxVisualization {
const {x, y} = points[i]
graphics.lineTo(x, y)
}
if (points.length > 0) {
const last = points[points.length - 1]
this.ripples.addRipple(last.x, last.y)
}

graphics.stroke({width: 4, color: colours[recordingId % colours.length]});
}

Expand All @@ -153,4 +163,57 @@ export class Visualization implements TheremaxVisualization {

this.app.stage.addChild(this.progress);
}
}

class Ripples {
private readonly maxRipples = 32
private readonly maxAgeMs = 300
readonly graphics = new Graphics()
readonly ripples: { x: number, y: number, creation: number, graphics: Graphics }[] = []

addRipple(x: number, y: number) {
while (this.ripples.length >= this.maxRipples) {
const stale = this.ripples.shift()
if (!stale) {
throw new Error("Impossible")
}
this.graphics.removeChild(stale.graphics)
}
const creation = Date.now()
const radius = this.radius(creation);
const alpha = this.fade(creation)
const graphics = new Graphics().circle(x, y, radius).fill({ r: 1, g: 255, b: 3, a: alpha})
this.ripples.push({ x, y, creation, graphics})
this.graphics.addChild(graphics)
}

tick() {
const now = Date.now()
while (this.ripples.length > 0 && this.ripples[0].creation + this.maxAgeMs < now) {
// assuming ripples is sorted...
const stale = this.ripples.shift()
if (!stale) {
throw new Error("Impossible")
}
this.graphics.removeChild(stale.graphics)
}
for (const ripple of this.ripples) {
const { x, y, creation } = ripple
const radius = this.radius(creation);
const alpha = this.fade(creation)
ripple.graphics.clear().circle(x, y, radius).stroke({ r: 255, g: 255, b: 3, a: alpha})
}
}

fade(creation: number) {
const age = Date.now() - creation
if (age === 0) {
return 1;
}
return lerp(age, 0, this.maxAgeMs, 1, 0)
}

radius(creation: number) {
return (Date.now() - creation)
}
}
5 changes: 5 additions & 0 deletions src/components/lerp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export function lerp(value: number, sourceRangeMin: number, sourceRangeMax: number, targetRangeMin: number, targetRangeMax: number) {
const targetRange = targetRangeMax - targetRangeMin;
const sourceRange = sourceRangeMax - sourceRangeMin;
return (value - sourceRangeMin) * targetRange / sourceRange + targetRangeMin;
}

0 comments on commit 802ef03

Please sign in to comment.