Published
Edited
Feb 13, 2021
11 stars
Hello, PGLiteINSEE ParquetHello, apcachDruidJS workerHello, OrbitWord Tour: 40k words and their friendsHello, spectral.jsHello, petite-vueHello, @thi.ng/grid-iteratorsHello, thumbhashHello, SwissGLHello, QOI (and glitches)Hello, orbHello, cosmographHello, TabulatorUsing d3.blur with PlotMath.cbrtHello debounceColorcetHello, gliiHello, Open MeteoHello, PyWaveletsHello, typesenseHello, libgifHello, kmeans-engineHappy anniversary, Project Gutenberg!Hello, fflateHello, ArchieML!Hello, d3-bboxCollideHello, jsgeoda!Hello, EDTF!Hello, protovis!Hello, placekeyHello, fuse.jsHello, Reorder.jsHello, shadow DOMjszipHello, procedural-glHello, qhullHello, genetic-jsDruidJSHello, Tippy.js
Hello, paintWorklet
Big πHello, AutoencoderHello, Shakespearean UUIDsHello, ccwt.jsHello, constrainautorHello, talismanHello, polygon-offsetHello p-queueHello async-poolHello rollup-plugin-asciiHello, algebra.jsHello, pixi.jsHello, d3-renderHello zip/unzipCumulative Wikipedia DonationsHTML <details>regl textureHello, npyjsHello protobufHello, pencil touchHello, LOESSHello html2canvaslegra mapscolor2cssHello, ecsy2D point distributionsHello, delatinThe gpu.js loopDijkstra’s shortest-path treeHello nojacko/Dijkstras-jsHello, tcort/dijkstrajsHello, lambdabaa/dijkstraHello, gpu.js v2Hello jsqrHello qrcodeHello SharedArrayBufferHello GamePad APIHello vtk.jsHello nd4jsHello BiofabricTravelling with a self-organizing mapHello glitchHello UMAP-jsHello pandemoniumHello iocaneHello JSON-editorHello d3-griddingHello mljs/knnWorkerHello lalolibImage to GPU.jsImage to blink.jsTissot's indicatrixVega projectionsHello WebCLGLUsing d3-inertia with observableVideo contouring 3ngraph: pagerank, louvain…Union-FindPerceptron (simple statistics)mljsHello h3-jsEmoji FlagsHello, poisson-disk-sampling
Insert cell
Insert cell
Insert cell
// default styles for our div
html`<style>
.painted{
background: paint(${name});
--rotate: [0, 35];
--sphere-color: lightblue;
}`
Insert cell
// updates our div’s styles
animateCss = () =>
d3
.selectAll(".painted")
.interrupt()
.transition()
.ease(d3.easeBackInOut)
.duration(1000)
.style("--rotate", "[720, -15]")
.style("--sphere-color", d3.interpolateRainbow(Math.random()))
.transition()
.duration(5000)
.ease(d3.easeElasticInOut)
.style("--rotate", "[0, -35]")
.style("--sphere-color", "lightblue")
.transition()
.duration(100)
.style("--rotate", "[0, -35]")
Insert cell
// set the click handler on our div, an animate it once
d3
.select(text)
.selectAll(".painted")
.on("click", animateCss)
.style("cursor", "pointer")
.call(animateCss)
Insert cell
// the function we’ll send to the worklet. It only has access to the scripts defined in the preamble
painter = (name, { land }) => {
const projection = d3.geoOrthographic();
const path = d3.geoPath(projection);

let i = 0;

class Worklet {
static get inputProperties() {
return ['--sphere-color', '--rotate'];
}

paint(context, { width, height }, properties) {
console.log("running", i++);

path.context(context);
const rotate = JSON.parse(
properties
.get('--rotate')
.toString()
.trim()
);

projection
.fitExtent([[10, 10], [width - 10, height - 10]], { type: "Sphere" })
.rotate(rotate);

context.fillStyle = properties
.get('--sphere-color')
.toString()
.trim();
context.beginPath();
path({ type: "Sphere" });
context.fill();

context.beginPath();
path(land);
context.fillStyle = "white";
context.fill();

context.beginPath();
path({ type: "Sphere" });
context.stroke();
}
}

globalThis.registerPaint(name, Worklet);
}
Insert cell
// this should be d3-geo@2 when it's compatible, see https://github.com/d3/d3-delaunay/issues/111
preamble = `
import 'https://unpkg.com/d3@6';
`
Insert cell
name = register(preamble, {land})
Insert cell
register = (preamble = "", ...args) => {
const name = "aa" + Math.floor(Math.random() * 1e19);

CSS.paintWorklet.addModule(
"data:text/javascript;base64," +
btoa(
`${preamble};
(${painter.toString()})
(${JSON.stringify(name)},
${args.map(d => JSON.stringify(d))})
`
)
);
return name;
}
Insert cell
land = fetch(
"https://unpkg.com/visionscarto-world-atlas@0.0.6/world/110m_land.geojson"
).then(d => d.json())
Insert cell
Insert cell
// no d3-geo!
d3 = require("d3-selection@2", "d3-transition@2", "d3-ease@2", "d3-scale-chromatic@2")
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