diff --git a/examples/rdom-canvas-basics/package.json b/examples/rdom-canvas-basics/package.json index f129dca67c..6b61313212 100644 --- a/examples/rdom-canvas-basics/package.json +++ b/examples/rdom-canvas-basics/package.json @@ -16,10 +16,13 @@ "vite": "^4.4.9" }, "dependencies": { + "@thi.ng/compose": "workspace:^", + "@thi.ng/dsp": "workspace:^", "@thi.ng/geom": "workspace:^", "@thi.ng/rdom-canvas": "workspace:^", "@thi.ng/rstream": "workspace:^", - "@thi.ng/transducers": "workspace:^" + "@thi.ng/transducers": "workspace:^", + "@thi.ng/vectors": "workspace:^" }, "browser": { "process": false diff --git a/examples/rdom-canvas-basics/src/index.ts b/examples/rdom-canvas-basics/src/index.ts index f86b66ce2b..9bd27db7fb 100644 --- a/examples/rdom-canvas-basics/src/index.ts +++ b/examples/rdom-canvas-basics/src/index.ts @@ -1,34 +1,53 @@ +import { threadLast } from "@thi.ng/compose"; +import { osc, parabolic, sin } from "@thi.ng/dsp"; import { circle, group } from "@thi.ng/geom"; import { $canvas } from "@thi.ng/rdom-canvas"; import { fromRAF } from "@thi.ng/rstream"; -import { repeatedly } from "@thi.ng/transducers"; +import { mapIndexed, take, zip } from "@thi.ng/transducers"; +import type { Vec } from "@thi.ng/vectors"; -// create geometry stream/subscription -const geo = fromRAF().map((t) => - // shape group w/ attribs - group( - { - // fill canvas w/ background color (see readme) - __background: "#0ff", - }, +// create subscription for `requestAnimationFrame()` (RAF) events +// transform input timestamps into geometry +const geo = fromRAF().map((time) => + // generate geometry... + threadLast( + // 1. form coordinates by combining oscillators into tuples (2d points). + // used like this, the oscillators (and therefore `zip` too) are + // producing a lazy, but infinite(!) sequence... + zip( + // x-axis oscillator (see thi.ng/dsp readme) + // oscillators are also iterable, hence can be used with zip + osc(sin, 0.008, 150, 300, time / 300), + // y-axis oscillator (with different waveform & slightly offset phase) + osc(parabolic, 0.008, 150, 300, time / 100) + ), + // 2. only take first N values from the infinite sequence + [take, 100], + // 3. convert points into colored circles: + // unlike in e.g. Processing/p5.js these are **NOT** drawing commands! + // here we're purely generating 2d shapes, which could be + // used in many different ways (incl. for drawing to a canvas, as done + // further below, but at this point there're just data...) [ - // create 10 circles - ...repeatedly( - (i) => - circle( - [ - Math.sin(t * 0.01 + i * 0.5) * 150 + 300, - Math.sin(t * 0.03 + i * 0.5) * 150 + 300, - ], - 50, - // colors can be given as RGBA vectors or CSS - { fill: [i * 0.1, 0, i * 0.05] } - ), - 10 - ), + mapIndexed, + (i: number, pos: Vec) => + circle( + pos, + 50, + // colors can be given as plain RGB(A) vectors or CSS strings + { stroke: [i * 0.01, 0, i * 0.005] } + ), + ], + // 4. wrap all shapes into a group shape node + [ + group, + // fill canvas w/ background color (see thi.ng/rdom-canvas readme) + { __background: "#0ff" }, ] ) ); -// create & mount canvas component (w/ fixed size) -$canvas(geo, [600, 600]).mount(document.getElementById("app")!); +// create & mount reactive canvas component (w/ fixed size). +// this DOM component subscribes to the above geometry stream and +// redraws the canvas with every update/frame... +$canvas(geo, [600, 600]).mount(document.body); diff --git a/yarn.lock b/yarn.lock index f8950643da..a143e76de3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1417,10 +1417,13 @@ __metadata: version: 0.0.0-use.local resolution: "@example/rdom-canvas-basics@workspace:examples/rdom-canvas-basics" dependencies: + "@thi.ng/compose": "workspace:^" + "@thi.ng/dsp": "workspace:^" "@thi.ng/geom": "workspace:^" "@thi.ng/rdom-canvas": "workspace:^" "@thi.ng/rstream": "workspace:^" "@thi.ng/transducers": "workspace:^" + "@thi.ng/vectors": "workspace:^" typescript: ^5.2.2 vite: ^4.4.9 languageName: unknown