diff --git a/bun.lockb b/bun.lockb
index f137ba7..b7bf71a 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/index.html b/index.html
index 44a9335..3504586 100644
--- a/index.html
+++ b/index.html
@@ -2,12 +2,11 @@
-
- Vite + TS
+ ripples | compost.party
-
+
diff --git a/package.json b/package.json
index 335a73b..801587e 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
},
"devDependencies": {
"typescript": "^5.2.2",
+ "typescript-language-server": "^4.3.1",
"vite": "^5.0.8"
}
}
diff --git a/src/counter.ts b/src/counter.ts
deleted file mode 100644
index 09e5afd..0000000
--- a/src/counter.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-export function setupCounter(element: HTMLButtonElement) {
- let counter = 0
- const setCounter = (count: number) => {
- counter = count
- element.innerHTML = `count is ${counter}`
- }
- element.addEventListener('click', () => setCounter(counter + 1))
- setCounter(0)
-}
diff --git a/src/main.ts b/src/main.ts
index 791547b..ec0d437 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,24 +1,73 @@
import './style.css'
-import typescriptLogo from './typescript.svg'
-import viteLogo from '/vite.svg'
-import { setupCounter } from './counter.ts'
-document.querySelector('#app')!.innerHTML = `
-
-
-
-
-
-
-
-
Vite + TypeScript
-
-
-
-
- Click on the Vite and TypeScript logos to learn more
-
-
-`
+const canvas = document.querySelector('#canvas')!
-setupCounter(document.querySelector('#counter')!)
+const ctx = canvas.getContext('2d')!
+
+const MIN_RADIUS = 20
+const MAX_RADIUS = 200
+const MAX_AGE = 5000 // in milliseconds
+
+type Particle = {
+ position: [number, number],
+ age: number
+}
+
+const createParticle = (x: number, y: number): Particle => ({
+ position: [x, y],
+ age: 0,
+})
+
+let state = {
+ particles: []
+}
+
+type State = typeof state
+
+canvas.addEventListener('click', (e) => {
+ // TODO Normalize x and y coords
+ const particle = createParticle(e.clientX, e.clientY)
+ state.particles.push(particle)
+})
+
+const update = (state: State, deltaTime: number): State => ({
+ particles: state.particles
+ .map(p => ({
+ ...p,
+ age: p.age + deltaTime
+ }))
+ .filter(p => p.age < MAX_AGE)
+})
+
+const render = (state: State, ctx: CanvasRenderingContext2D) => {
+ ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)
+
+ for (const particle of state.particles) {
+ const progress = (particle.age / MAX_AGE)
+ const opacity = Math.min(1, (1-progress)*(1-progress))
+
+ ctx.beginPath()
+ ctx.strokeStyle = `rgba(40, 40, 40, ${opacity})`
+ const [x, y] = particle.position
+ const radius = (progress * (MAX_RADIUS - MIN_RADIUS)) + MIN_RADIUS
+ ctx.ellipse(x, y, radius, radius, 0, 0, Math.PI * 2)
+ ctx.stroke()
+ }
+}
+
+let before = Date.now()
+const loop = () => {
+ const now = Date.now()
+ const dt = now - before
+ state = update(state, dt)
+ render(state, ctx)
+ before = now
+ requestAnimationFrame(loop)
+}
+
+document.addEventListener('DOMContentLoaded', () => {
+ canvas.width = canvas.parentElement!.clientWidth
+ canvas.height = canvas.parentElement!.clientHeight
+ ctx.translate(0.5, 0.5)
+ loop()
+})
diff --git a/src/style.css b/src/style.css
index f9c7350..92912df 100644
--- a/src/style.css
+++ b/src/style.css
@@ -1,96 +1,11 @@
-:root {
- font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
- line-height: 1.5;
- font-weight: 400;
-
- color-scheme: light dark;
- color: rgba(255, 255, 255, 0.87);
- background-color: #242424;
-
- font-synthesis: none;
- text-rendering: optimizeLegibility;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-
-a {
- font-weight: 500;
- color: #646cff;
- text-decoration: inherit;
-}
-a:hover {
- color: #535bf2;
-}
-
+html,
body {
- margin: 0;
- display: flex;
- place-items: center;
- min-width: 320px;
+ min-width: 100wh;
min-height: 100vh;
+ padding: 0;
+ margin: 0;
}
-h1 {
- font-size: 3.2em;
- line-height: 1.1;
-}
+canvas {
-#app {
- max-width: 1280px;
- margin: 0 auto;
- padding: 2rem;
- text-align: center;
-}
-
-.logo {
- height: 6em;
- padding: 1.5em;
- will-change: filter;
- transition: filter 300ms;
-}
-.logo:hover {
- filter: drop-shadow(0 0 2em #646cffaa);
-}
-.logo.vanilla:hover {
- filter: drop-shadow(0 0 2em #3178c6aa);
-}
-
-.card {
- padding: 2em;
-}
-
-.read-the-docs {
- color: #888;
-}
-
-button {
- border-radius: 8px;
- border: 1px solid transparent;
- padding: 0.6em 1.2em;
- font-size: 1em;
- font-weight: 500;
- font-family: inherit;
- background-color: #1a1a1a;
- cursor: pointer;
- transition: border-color 0.25s;
-}
-button:hover {
- border-color: #646cff;
-}
-button:focus,
-button:focus-visible {
- outline: 4px auto -webkit-focus-ring-color;
-}
-
-@media (prefers-color-scheme: light) {
- :root {
- color: #213547;
- background-color: #ffffff;
- }
- a:hover {
- color: #747bff;
- }
- button {
- background-color: #f9f9f9;
- }
}
diff --git a/src/typescript.svg b/src/typescript.svg
deleted file mode 100644
index d91c910..0000000
--- a/src/typescript.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file