Public
Edited
Aug 26, 2024
1 fork
Importers
12 stars
Insert cell
Insert cell
Insert cell
Insert cell
viewof layers = elementStack(this, {
width: Math.min(width, 400),
height: Math.min(width, 400),
layers: {
regl: ({ current, width, height }) =>
reglCanvas(current, { width, height }),
plot: ({ width, height }) =>
Plot.plot({
width,
style: { backgroundColor: "transparent", maxWidth: "none" },
aspectRatio: 1,
x: { grid: true, domain: [-1, 1] },
y: { grid: true, domain: [-1, 1] },
marks: [
Plot.frame(),
Plot.ruleY([0]),
Plot.ruleX([0]),
Plot.line(
[
[-0.5, -0.5],
[0.5, -0.5],
[0, 0.5],
[-0.5, -0.5]
],
{ strokeWidth: 4 }
)
]
})
}
})
Insert cell
regl = layers.regl.value
Insert cell
configureAxes = createAxisConfiguration(regl)
Insert cell
{
const xaxis = layers.plot.scale("x");
const yaxis = layers.plot.scale("y");

regl.poll();
configureAxes(xaxis, yaxis, () => {
drawTriangle();
});
}
Insert cell
drawTriangle = regl({
vert: `
precision highp float;
attribute vec2 xy;
attribute vec3 color;
uniform mat4 view;
varying vec3 vColor;
void main () {
vColor = color;
gl_Position = view * vec4(xy, 0, 1);
}`,
frag: `
precision lowp float;
varying vec3 vColor;
void main () {
gl_FragColor = vec4(pow(vColor, vec3(1.0 / 2.2)), 1);
}`,
attributes: {
xy: [-0.5, -0.5, 0.5, -0.5, 0, 0.5],
color: [
[1, 0, 0],
[0, 1, 0],
[0, 0, 1]
]
},
primitive: "triangles",
count: 3,
depth: { enable: false }
})
Insert cell
Insert cell
Insert cell
function elementStack(
currentStack,
{ width = null, height = null, layers = {}, onResize = null } = {}
) {
const container = currentStack || document.createElement("figure");
container.style.position = "relative";
if (!currentStack && onResize) {
const observer = new ResizeObserver(([{ contentRect }]) => {
onResize({ layers: container.value, rect: contentRect });
container.dispatchEvent(new CustomEvent("input"));
});
observer.observe(container);
}
const stack = {};
let defaultZindex = 0;
for (const [label, props] of Object.entries(layers)) {
const layer = typeof props === "function" ? props : props.layer;
const id = `element-stack-layer-${label}`;
const current = container.querySelector(`#${id}`);
const newEl = layer({ current, width, height });
newEl.setAttribute("id", id);
if (!newEl.style.position) newEl.style.position = "absolute";
stack[label] = newEl;
if (current) {
current.replaceWith(newEl);
} else {
container.appendChild(newEl);
}
}
if (width) container.style.width = `${width}px`;
if (height) container.style.height = `${height}px`;
container.value = stack;
return container;
}
Insert cell
Insert cell
import { mat4create, mat4ortho, mat4invert } from "@rreusser/gl-mat4"
Insert cell
function createAxisConfiguration(regl) {
const configureAxes = regl({
uniforms: {
view: regl.prop("view"),
viewInverse: regl.prop("viewInverse")
},
context: {
view: regl.prop("view"),
viewInverse: regl.prop("viewInverse")
},
scissor: {
enable: true,
box: {
x: ({ pixelRatio }, { xRange: [xmin, xmax] }) => xmin * pixelRatio,
y: ({ pixelRatio, framebufferHeight }, { yRange: [ymax, ymin] }) =>
framebufferHeight - ymax * pixelRatio,
width: ({ pixelRatio }, { xRange: [xmin, xmax] }) =>
(xmax - xmin) * pixelRatio,
height: ({ pixelRatio }, { yRange: [ymax, ymin] }) =>
(ymax - ymin) * pixelRatio
}
},
viewport: {
x: ({ pixelRatio }, { xRange: [xmin, xmax] }) => xmin * pixelRatio,
y: ({ pixelRatio, framebufferHeight }, { yRange: [ymax, ymin] }) =>
framebufferHeight - ymax * pixelRatio,
width: ({ pixelRatio }, { xRange: [xmin, xmax] }) =>
(xmax - xmin) * pixelRatio,
height: ({ pixelRatio }, { yRange: [ymax, ymin] }) =>
(ymax - ymin) * pixelRatio
}
});

const view = mat4create();
const viewInverse = mat4create();

return function (xScale, yScale, callback) {
mat4ortho(view, ...xScale.domain, ...yScale.domain, -1, 1);
mat4invert(viewInverse, view);
configureAxes(
{ view, viewInverse, xRange: xScale.range, yRange: yScale.range },
callback
);
};
}
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