Stream of Points

We construct some generators to emit a stream of points.

//frame.wiki.dbbs.co/assets/pages/snippet-template/esm.html SOURCE point

To watch the points drawn, see Scribble.

function* genPoints() { const {floor, random} = Math const average = 15 let [x, y] = [0, 0] while (true) { yield {x, y} x += floor(average * (random()-random())) y += floor(average * (random()-random())) } }

Infinite streams risk infinite loops. We can construct another generator which limits the range of the stream.

function* take(n, iterator) { let result, i = 0; while (!(result = iterator.next()).done && i++ < n) { yield result.value; } }

Lets introduce a little asynchrony to more closely model a stream of mouse movements.

async function* timejitter(iterator) { const {floor, random} = Math const average = 200 for (let point of iterator) { yield point let ms = floor(average * (random()-random())) await new Promise(r => setTimeout(r, ms)) } }

We create a few helper functions.

function resize() { window.parent.postMessage({ action: "resize", height: document.body.offsetHeight }, "*") }

function broadcast(point) { window.parent.postMessage({ action: "publishSourceData", name: "point", sourceData: {point} }, "*") }

function updateProgress(el, count) { el.innerHTML = `generated ${count} points` }

Let's broadcast a line.

export async function emit(el) { const now = new Date().toLocaleString("en-US") el.innerHTML = ` <p>started: ${now}</p> <p id="progress"></p>` } export async function bind(el) { const display = el.querySelector("#progress") let progress = 0 updateProgress(display, progress) resize() const line = timejitter(take(1000, genPoints())) for await (let point of line) { broadcast(point) if (progress % 25 == 0) { updateProgress(display, progress) } progress++ } const now = new Date().toLocaleString("en-US") updateProgress(display, progress) display.insertAdjacentHTML("afterend", ` <p>stopped: ${now}</p>`) resize() }