Public
Edited
Jan 3, 2024
Fork of Scribble
11 stars
Insert cell
Insert cell
Insert cell
Insert cell
{
const context = canvas.getContext('2d')
context.imageSmoothingEnabled = true;
const s = new SimplexNoise(myseed.value)
var w = context.canvas.width,
h = context.canvas.height,
w2 = w / 2,
h2 = h / 2
var x = w >> 1, y = h >> 1
var newx = x, newy = y
var overx = 0, overy = 0
const theta = 0.5
var wsin = 0
var frames = 0
var beta = 800
function step() {
// if (++frames == 950) {
if (++frames % 15 == 100) {
frames = 0
}
if (++beta == 100) {
beta = 0
}
//let this_speed = 50 * Math.cos(3.141592 * (speed.value / 100))
let this_speed = (101 - speed.value)
let points = scribble(
frames / this_speed,
beta / 400 + Math.sin(2 * 3.141592 * (beta / 800)),
beta / 2000
)
// var previous_frame = context.getImageData(0, 0, w, h)
// context.putImageData(previous_frame)
// context.clearRect(0, 0, w, h)
context.fillRect(0, 0, w, h)
for (var i = 0; i < points.length; i++) {
newx = w2 + w2 * points[i][0]
newy = h2 + h2 * points[i][1]
context.beginPath()
context.moveTo(x, y)
overx = newx - x
overy = newy - y
if (i > 0) {
context.lineTo(newx + 0.3 * overx, newy + 0.3 * overy)
context.moveTo(newx, newy)
}
context.lineWidth = 1 + Math.abs(18 * s.noise3D(points[i][0], points[i][1], -1))
context.strokeStyle = "#FFFFFF"
context.stroke()
x = newx
y = newy
}
window.requestAnimationFrame(step)
}
window.requestAnimationFrame(step)
}
Insert cell
scribble = (theta, beta, gfreq) => {
const resolution = 1000
const s = new SimplexNoise(myseed.value)
return arcs01(resolution).map(t => {
const angle = t * Math.PI * 2
// const freq = 1.0
// const amplitude = 0.75;
let point = torus(0.25, 1, angle, theta)
point[0] *= freq.value * gfreq
point[1] *= freq.value * gfreq
point[2] *= freq.value * gfreq
const [x, y, z] = point
//let tt = t; //Math.sin(2 * 3.141592 * t)
let tt = beta //Math.sin(0.5 + 3.141592 * 3 * beta)
return [
// amplitude.value * s.noise4D(x, y, z, (-zslider.value)),
// amplitude.value * s.noise4D(x, y, z, (+zslider.value))
amplitude.value * s.noise4D(x, y, z, -tt - 1 * zslider.value),
amplitude.value * s.noise4D(x, y, z, +tt + 1 * zslider.value)
]
})
}
Insert cell
SimplexNoise = require('simplex-noise@2')
Insert cell
array = n => Array.from(new Array(n))
Insert cell
arcs = n => array(n).map((_, i) => i / n)
Insert cell
arcs01 = n => array(n).map((_, i) => (
n <= 1 ? 0 : i / (n - 1)
))
Insert cell
torus = (a, c, u, v, out = []) => {
out[0] = (c + a * Math.cos(v)) * Math.cos(u)
out[1] = (c + a * Math.cos(v)) * Math.sin(u)
out[2] = a * Math.sin(v)
return out
}
Insert cell
arcs(5)
Insert cell
arcs01(5)
Insert cell
amplitude = {
var x = DOM.range(0, 2)
x.value = 1
return(x)
}
Insert cell
freq = {
var x = DOM.range(0, 0.7)
x.value = 0.15
return(x)
}
Insert cell
zslider = {
var x = DOM.range(-1, 1)
x.value = -0.4
return(x)
}
Insert cell
speed = {
var x = DOM.range(1, 100)
x.value = 15
return(x)
}
Insert cell
myseed = DOM.range(0, 1e7, 1e3)
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