Public
Edited
Jun 9, 2024
12 stars
Also listed in…
regl
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
<div id="big-container" width=width height=${height}>
<div id="svg-container" width=width height=${height} style="position: absolute">
<svg id="svg"></svg>
</div>
<div id="container" style="width: 800px; height: 520px;"></div>
</div>
Insert cell
Insert cell
Insert cell
{
const svg = d3
.select("#svg")
// .append("svg")
.attr("width", width)
.attr("height", height);

const arrayY = ["group 0", "group 1", "group 2", "group 3", "group 4"];

// regl scale to svg scale
const svgYScale = d3.scaleLinear().domain([-1, 1]).range([height, 0]);

svg
.selectAll("text")
.data(arrayY)
.enter()
.append("text")
.text((d) => d)
.attr("x", 800 + 15)
.attr("y", (d, i) => svgYScale(yScale(i)) - 15);

return svg.node();
}
Insert cell
Insert cell
drawREGL()
Insert cell
function drawREGL() {
d3.select("#container").html("");

// init regl
const container = document.getElementById("container");

const regl = createREGL({
container: container
// extensions: ["OES_standard_derivatives"]
});

// draw points
const drawPoints = regl({
vert: `
precision mediump float;
attribute float speed, x, y0, y1, dy;
attribute float isB;
varying float c;
uniform float interp; // time / 40

void main() {
// 점의 이동거리: x + interp * speed (초기위치 + 시간 * 속도)
// mod(A, B) -> 나머지 계산, B가 1 이므로 (0, 1) 사이의 값 반환 (오른쪽 끝에가면 다시 원점에서 시작되게 됨)
// x축 보간인자 (일정하게 증가함)
float t = mod(x + interp * speed, 1.0);

// cubic ease
// y축 보간인자 (천천히 증가하다가 0.5에서 급격히 증가하고 천천히 감속함) (t값에 의해 정해짐)
float ct = t < 0.5
? 4.0 * t * t * t //시작할 때 천천히 움직이다가 점점 빨라지는 가속
: -0.5 * pow(abs(2.0 * t - 2.0), 3.0) + 1.0; // 천천히 감속하면서 끝남

// mix(A, B, c) -> A(시작), B(끝), c(보간인자, 0 - 1사이) -> linear interpolation
float x = mix(-1.0, 1.0, t);
float y = mix(y0, y1, ct);

gl_Position = vec4(x, y + dy, 0, 1);
gl_PointSize = 3.0; /// 4.0

c = isB;
}`,

frag: `
precision mediump float;
varying float c;
void main() {
vec4 blue = vec4(0.00, 0.65, 1.00, 1);
// vec4 orng = vec4(0.99, 0.45, 0.011, 1);
vec4 orng = vec4(1.0, 0.8, 0.2, 1);

gl_FragColor = c == 1.0 ? blue : orng;
}`,

// Without using buffer
// attributes: {
// speed: data.map((d) => d.speed),
// x: data.map((d) => d.x),
// y0: data.map((d) => d.y0),
// y1: data.map((d) => d.y1),
// dy: data.map((d) => d.dy),
// isB: data.map((d) => d.isB)
// },

// Using buffer
attributes: {
speed: { buffer: regl.buffer(data.map((d) => d.speed)) },
x: { buffer: data.map((d) => d.x) },
y0: { buffer: data.map((d) => d.y0) },
y1: { buffer: data.map((d) => d.y1) },
dy: { buffer: data.map((d) => d.dy) },
isB: { buffer: data.map((d) => d.isB) }
},

uniforms: {
interp: (ctx, props) => props.interp
},

primitive: "points",

count
});

// regl rendering
regl.frame(({ time }) => {
regl.clear({
depth: 1,
color: [0.1, 0.1, 0.1, 1]
// color: [1, 1, 1, 1]
});

drawPoints({ interp: time / 40 });
});
}
Insert cell
Insert cell
Insert cell
Insert cell
data = d3.range(count).map((i) => {
// 나머지 0 아니면 1
var isB = i % 2;
// (i / count)는 0에서 1 사이의 값을 가짐 -> 값이 일정하게 증가함
var q = (isB ? bScale : wScale)(i / count);

return {
speed: Math.random() * 2 + 1,
x: Math.random() * 2 - 1,
y0: yScale(0), // y0 고정
y1: yScale(q), // bScale or wScale 반환값에 따라 다름
dy: Math.random() * 0.2,
isB
};
})
Insert cell
data.map((d) => d.speed)
Insert cell
6 % 2
Insert cell
count = 20000 // 20000
Insert cell
Insert cell
Insert cell
// determin y1 using yScale
// 확률에 따라 0 - 4 값 반환
bScale = d3
.scaleThreshold()
.domain([0.21, 0.42, 0.63, 0.83])
.range([0, 1, 2, 3, 4])
Insert cell
d3.range([0.21, 0.42, 0.63, 0.83].length + 1)
Insert cell
// determin y1 using yScale
// 확률에 따라 0 - 4 값 반환
wScale = d3
.scaleThreshold()
.domain([0.1, 0.2, 0.35, 0.6])
.range([0, 1, 2, 3, 4])
Insert cell
// 0 - 4 값을 y축 값으로 반환
yScale = d3.scaleLinear().domain([0, 4]).range([-0.8, 0.8])
Insert cell
Insert cell
Insert cell
// regl = await import("https://cdn.skypack.dev/regl@2") // not working -> this is for rendering from a canvas
// createREGL = require("https://npmcdn.com/regl/dist/regl.min.js") // working
createREGL = require("regl") // working
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