Public
Edited
Feb 27
Importers
4 stars
Insert cell
Insert cell
Insert cell
Insert cell
class Walker {
constructor({x=0, y=0, color='#000'}={}) {
this.x = x
this.y = y
this.color = color
}
step() {
this.x += randInt(-1, 1)
this.y += randInt(-1, 1)
}
set({x,y}){
this.x = x
this.y = y
}
display(ctx) {
ctx.fillStyle = this.color
ctx.fillRect(this.x, this.y, 1, 1)
}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
class RightDownBiasedWalker extends Walker {
step() {
// 'hard' bias, by increasing probability of right/down movements
this.x += clamp(randInt(-1, 2), -1, 1)
this.y += clamp(randInt(-1, 2), -1, 1)
}
}
Insert cell
Insert cell
Insert cell
Insert cell
probTableRng = probTable => {
// sanitise table:
const probsSum = _.sumBy(probTable, ([val, prob]) => prob || 0);
const restProbItems = probTable.filter(([val, prob]) => prob == null).length;
if (probsSum < 1 && restProbItems === 0) {
throw Error('all probs should sum to 1, or at least one be left without prob')
}
const defaultProb = restProbItems === 0 ? 0 : Math.max(0, 1.0 - probsSum) / restProbItems;
return () => {
const rnd = random();
let cursor = 0;
for (let [val, prob] of probTable) {
cursor += (prob != null ? prob : defaultProb);
if (rnd < cursor) return val;
}
}
}
Insert cell
pachinko(probTableRng([[1,0.1],[2,0.2], [3], [4, 0.1], [5, 0.2]]))
Insert cell
Insert cell
md`The probablity is **${ roundedPercent((4 / 52) ** 2) }%**`
Insert cell
Insert cell
class PointerFallowingWalker extends Walker {
step(mousePos) {
const prefered = mousePos && directionFromMousePos(this, mousePos)
const probs = directions.map(dir => _.isEqual(prefered, dir) ? [dir, 0.5] : [dir])
const [x, y] = probTableRng(probs)()

this.x += x
this.y += y
}
}
Insert cell
Insert cell
Insert cell
Insert cell
directionFromMousePos = (p, m) => {
const pa = Math.atan2(m.y - p.y, m.x - p.x)
const ai = _.findIndex(angles, (a) => angleDist(a, pa) <= PI / 8)
return directions[ai]
}
Insert cell
directions = [[-1, 0], [-1, -1], [0, -1], [1, -1], [1, 0], [1, 1], [0, 1], [-1, 1]]
Insert cell
angles = _.range(-PI, PI, PI / 4)
Insert cell
Insert cell
normal = d3.randomNormal.source(random)()
Insert cell
pachinko(normal)
Insert cell
Insert cell
pachinko(() => normal() * 15 + 100) // mean = 100, sd = 15
Insert cell
{
const height = 100
const mean = width / 2
const sd = width / 8
const ctx = DOM.context2d(width, height)
let x = width / 2
let y = height / 2
let r = 20
for (let i = 0; i < 300; ++i) {
x = normal() * sd + mean
ctx.beginPath()
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)'
ctx.arc(x, y, r, 0, 2 * PI)
ctx.fill()
yield ctx.canvas
}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
class NormalDistStep360Walker extends RandomStep360Walker {
stepLength() {
const l = Math.abs(normal() * distStepSigma)
// little coloring magic
this.color = tinycolor(this.color).setAlpha(Math.min(0.1 + l / (3 * distStepSigma), 1)).toString()
return 1 + l
}
}
Insert cell
Insert cell
Insert cell
Insert cell
class ParetoStep360Walker extends RandomStep360Walker {
constructor(...args) {
super(...args)
this.rng = d3.randomPareto.source(random)(paretoAlpha)
}
stepLength() {
const l = this.rng()
// little coloring magic
this.color = tinycolor(this.color).setAlpha(Math.min(0.1 + l/100, 1)).toString()
return l
}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
class ExpWalker extends RandomStep360Walker {
constructor(...args){
super(...args)
this.rng = montecarloDistrib(r => r * r)
}
step() {
const stepSize = 10 * this.rng()
this.px = this.x
this.py = this.y
this.x += randInt(-1, 1) * stepSize
this.y += randInt(-1, 1) * stepSize
// hack for externally done clamping
this.ox = this.x
this.oy = this.y
}
}
Insert cell
montecarloDistrib = (fn) => () => {
while(true) {
const r1 = random()
const prob = fn(r1)
if (random() < prob) {
return r1
}
}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
class PerlinDir360Walker extends RandomStep360Walker {
constructor(...args){
super(...args)
this.xoff = 0
this.angle = 0
}
step() {
this.xoff += noise_walker_x_step
const l = noise_walker_step_size
if (walker_stepping_style === 'diff') {
this.angle = this.angle + (noise1D(this.xoff) * PI - PI / 2)
} else {
this.angle = noise1D(this.xoff) * 2 * PI
}

this.px = this.x
this.py = this.y
this.x += l * Math.cos(this.angle)
this.y += l * Math.sin(this.angle)
// hack for externally done clamping
this.ox = this.x
this.oy = this.y
}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
const height = 200
const width = 200
const ctx = DOM.context2d(width, height)
const clr = tinycolor(noise_2d_display_color).toHsv()
for (let x = 0; x < width; ++x) {
for (let y = 0; y < height; ++y) {
const v = noise2D(x * noise_2d_display_step_xoff, y * noise_2d_display_step_yoff)
ctx.fillStyle = tinycolor(_.defaults({v}, clr)).toRgbString()
ctx.fillRect(x, y, 1, 1)
}
}
return ctx.canvas
}
Insert cell
Insert cell
Insert cell
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
import { threeScene } from '@ajur/threejs'
Insert cell
SimplexNoise = require('simplex-noise@2.4')
Insert cell
simplex = new SimplexNoise(random)
Insert cell
{
let n = 0;
const noise = () => simplex.noise2D(n++ / 100, n++);
return pachinko(noise);
}
Insert cell
noise1D = (x) => (simplex.noise2D(x, 1) + 1) * 0.5
Insert cell
noise2D = (x, y) => (simplex.noise2D(x, y) + 1) * 0.5
Insert cell
noise3D = (x, y, z) => (simplex.noise3D(x, y, z) + 1) * 0.5
Insert cell
angleDist = (a, a0) => {
let ang = a0 - a;
ang += ang > PI ? -2 * PI : ang < -PI ? 2 * PI : 0
return Math.abs(ang)
}
Insert cell
PI = Math.PI
Insert cell
roundedPercent = num => Math.round(num * 1000) / 10
Insert cell
randColor = () => '#' + _.times(6, () => randInt(0, 16).toString(16)).join('')

Insert cell
repeat = (fn, times) => {
while (times--) {
fn()
}
}
Insert cell
clamp = (x, min, max) => Math.max(Math.min(x, max), min)
Insert cell
wrap = (x, min, max) => modulo(x - min, max - min) + min
Insert cell
modulo = (a, n) => a - n * Math.floor(a / n) // after D. Knuth
Insert cell
randInt = (min, max) => Math.floor(random() * (max - min + 1) + min)
Insert cell
import {pachinko} from '@d3/d3-random'
Insert cell
random = seedrandom()
Insert cell
seedrandom = require("seedrandom/seedrandom.min.js")
Insert cell
d3 = require("d3-random")
Insert cell
import {slider, color, radio} from '@jashkenas/inputs'
Insert cell
_ = require('lodash')
Insert cell
tinycolor = require("tinycolor2")
Insert cell
import { THREE } from "@ajur/threejs"
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more