Published
Edited
Apr 14, 2022
5 stars
Insert cell
Insert cell
Insert cell
viewof regl = reglCanvas(this, { width: 256, height: 256 })
Insert cell
Insert cell
Insert cell
function createCropTransformer(w0, h0) {
const offset = new Float32Array(2);
const scale = new Float32Array(2);

return function crop({ x, y, width: w, height: h } = {}) {
offset[0] = x / w0;
offset[1] = y / h0;
scale[0] = w / w0;
scale[1] = h / h0;
return { offset, scale };
};
}
Insert cell
texture = regl.texture({
data: await FileAttachment("img.jpg").image(),
flipY: true
})
Insert cell
imageSize = [128, 128]
Insert cell
crop = createCropTransformer(128, 128)
Insert cell
// We sort of do and then undo the math here since the range is consistent
// with the slider and x/y/width/height is consistent with regl rects
transform = crop({
x: xrange[0],
y: yrange[0],
width: xrange[1] - xrange[0],
height: yrange[1] - yrange[0]
})
Insert cell
(regl.poll(), draw({ texture, transform }))
Insert cell
draw = regl({
vert: `
precision highp float;
attribute vec2 xy;
varying vec2 uv;

struct Transform { vec2 scale, offset; };
uniform Transform transform;

void main () {
uv = transform.offset + transform.scale * (0.5 * (xy + 1.0));
gl_Position = vec4(xy, 0, 1);
}`,
frag: `
precision highp float;
uniform sampler2D tex;
varying vec2 uv;
void main () {
gl_FragColor = texture2D(tex, uv);
}`,
attributes: {
xy: [
[-4, -4],
[4, -4],
[0, 4]
]
},
uniforms: {
tex: regl.prop("texture"),
"transform.offset": regl.prop("transform.offset"),
"transform.scale": regl.prop("transform.scale")
},
count: 3
})
Insert cell
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