commit e8cdcb3c25d66e3a0744509c6d36d14e275a6012
parent f2d8c4e4e2b5d04751bdb69fa715b8809227576c
Author: massi <mdsiboldi@gmail.com>
Date: Tue, 20 Jun 2023 20:59:30 -0700
basic visual synth
Diffstat:
5 files changed, 119 insertions(+), 2 deletions(-)
diff --git a/src/app.html b/src/app.html
@@ -10,3 +10,13 @@
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>
+
+
+<style>
+ html {
+ overflow: hidden;
+ }
+ body {
+ margin: auto;
+ }
+</style>
diff --git a/src/routes/+error.svelte b/src/routes/+error.svelte
@@ -0,0 +1 @@
+<h1>Doggone it</h1>
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
@@ -0,0 +1 @@
+<slot />
diff --git a/src/routes/+page.js b/src/routes/+page.js
@@ -0,0 +1 @@
+export const ssr = false;
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
@@ -1,2 +1,106 @@
-<h1>Welcome to SvelteKit</h1>
-<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>
+<script lang="ts">
+ import { onMount } from 'svelte';
+ let cvs: HTMLCanvasElement;
+
+ onMount(() => {
+ const resizeObserver = new ResizeObserver((entries) => {
+ const entry = entries.find((entry) => entry.target === cvs);
+ if (entry) {
+ cvs.width = entry.devicePixelContentBoxSize[0].inlineSize;
+ cvs.height = entry.devicePixelContentBoxSize[0].blockSize;
+ }
+ });
+
+ resizeObserver.observe(cvs);
+ if (cvs) resizeObserver.observe(cvs, { box: 'device-pixel-content-box' });
+
+ // This callback cleans up the observer
+ return () => resizeObserver.unobserve(cvs);
+ });
+
+ let t = 0;
+
+ function step() {
+ t = (t + 1) % 1000000000000; // lol
+ }
+
+ type Binding = () => number;
+
+ function mkOsc(inputs: { rate: Binding; amount: Binding }): Binding {
+ let { rate, amount } = inputs;
+ return () => (Math.sin(2 * Math.PI * t * rate()) - 0.5) * amount();
+ }
+
+ function combinatorBinding(...bindings: Binding[]): Binding {
+ return () => bindings.reduce((a, b) => a + b(), 0);
+ }
+
+ function constBinding(value: number): Binding {
+ return () => value;
+ }
+
+ function drawSquares(ctx: CanvasRenderingContext2D) {
+ if (!cvs) {
+ return;
+ }
+ const cols = 100;
+ const rows = 200;
+ let color = [128, 128, 128];
+ let width = cvs.width;
+ let height = cvs.height;
+ let paneWidth = Math.ceil(width / cols);
+ let paneHeight = Math.ceil(height / rows);
+
+ let osc1 = mkOsc({
+ rate: combinatorBinding(
+ constBinding(0.761243),
+ mkOsc({ rate: () => 0.0001, amount: () => 0.01 })
+ ),
+ amount: constBinding(30)
+ });
+ let osc2 = mkOsc({
+ rate: combinatorBinding(
+ mkOsc({ rate: () => 0.00001, amount: () => 1 }),
+ constBinding(0.881242)
+ ),
+ amount: constBinding(55)
+ });
+ let osc3 = mkOsc({ rate: constBinding(0.000001), amount: constBinding(255) });
+
+ const red = combinatorBinding(constBinding(128), osc1);
+ const green = combinatorBinding(constBinding(128), osc2);
+ const blue = combinatorBinding(constBinding(128), osc3);
+ for (let row = 0; row < rows; row++) {
+ for (let col = 0; col < cols; col++) {
+ step();
+ color[0] = red();
+ color[1] = green();
+ color[2] = blue();
+ ctx.fillStyle = `rgb(${color.join(', ')})`;
+ let x = col * paneWidth;
+ let y = row * paneHeight;
+ ctx.fillRect(x, y, paneWidth, paneHeight);
+ }
+ }
+ }
+ function run() {
+ requestAnimationFrame((t) => {
+ drawSquares(cvs.getContext('2d'));
+ run();
+ });
+ }
+
+ $: if (cvs) {
+ run();
+ }
+</script>
+
+<canvas bind:this={cvs} />
+
+<style>
+ canvas {
+ width: 100vw;
+ height: 100vh;
+ background: salmon;
+ }
+</style>