Published
Edited
Apr 24, 2020
1 star
Insert cell
md`# Noise graph`
Insert cell
SimplexNoise = require('https://cdnjs.cloudflare.com/ajax/libs/simplex-noise/2.4.0/simplex-noise.min.js')
Insert cell
// initialize only once: boot-up process is very expensive
// simplex = new SimplexNoise(seed)
// simplex.noise2D(x, y)
Insert cell
row = 15
Insert cell
column = 500
Insert cell
noiseHeight = 100
Insert cell
smoothFactor = .3
Insert cell
scaleBaseNoise = d3.scaleLinear([-1, 1], [-noiseHeight / 10, noiseHeight / 10])
Insert cell
getBaseNoise = () => {
const y = Math.random();
const baseNoises = Array.from({ length: column }).map((d, i) => {
const simplex = new SimplexNoise();
const val = simplex.noise2D(i, Math.random());
return scaleBaseNoise(val);
});
return baseNoises;
}
Insert cell
testBaseNoise = getBaseNoise()
Insert cell
smoothNoise = ns => ns.map(d => d * smoothFactor)
Insert cell
scalePulseNoise = d3.scaleSqrt([-1, 1], [0, noiseHeight * 2])
Insert cell
getPulseNoise = () => {
const y = Math.random();
const pulseNoises = Array.from({ length: column }).map((d, i) => {
const simplex = new SimplexNoise();
const val = simplex.noise2D(i, Math.random());
return scalePulseNoise(val);
});
return pulseNoises;
}
Insert cell
smoothNoise(testBaseNoise)
Insert cell
getPulseNoise()
Insert cell
delay = 70
Insert cell
{
let noiseHistory = [];
let noises = Array.from({ length: column }).map((_, i) => 0);
let i = 0;
while (true) {
await Promises.tick(delay, ++i);
const baseNoises = getBaseNoise();
noises = noises.map((d, i) => d + baseNoises[i]);
noises = smoothNoise(noises);
if (i % 5000 === 0) {
const pulses = getPulseNoise();
noises = noises.map((d, i) => d + pulses[i]);
}
noiseHistory.push(noises);
if (noiseHistory.length >= 20) noiseHistory.shift();
graph.render(noiseHistory);
yield null;
}
}
Insert cell
graph = {
const svg = d3
.create('svg')
.attr('width', config.width)
.attr('height', config.height);

const scaleX = d3
.scaleLinear()
.domain([0, column])
.range([0, config.width]);
// const scaleY = d3.scaleLinear().domain([-100, 100]).range([0, 100])
const getLine = d3
.line()
.x((d, i) => scaleX(i))
.y(d => d);

const updatePathCoord = path =>
path.datum(d => d).attr('transform', (d, i) => trans(0, i * 10));

const updatePathD = path => path.attr('d', getLine);

const enterPath = path =>
path
.append('path')
.attr('fill', 'none')
.attr('stroke', 'black')
.attr('stroke-width', '1px')
.call(updatePathCoord)
.call(updatePathD);

const updatePath = path => path.call(updatePathCoord).call(updatePathD);

function render(noiseHistory) {
// d[0] as id
svg
.selectAll('path')
.data(noiseHistory, ([id]) => id)
.join(enterPath, updatePath, node => node.remove());
}

return Object.assign(svg.node(), { render });
}
Insert cell
config = ({
width: width,
height: 150
})
Insert cell
import { trans, ttrans } from '@rabelais/d3-lib-2'
Insert cell
d3 = require('d3@5.15.0')
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