Public
Edited
Feb 10
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
const loop = newRegl.frame(function(context) {
// Each loop, update the data
updateData(points);

if (context.tick < 2) {
console.log(context);
}

// And draw it!
drawDots({
pointWidth: POINT_SIZE,
points: points
});
});

// dispose of previous webGL context
invalidation.then(() => loop.cancel());
}
Insert cell
// dots as circles
drawDots = newRegl({
frag: `
precision mediump float;
uniform vec4 color;
void main () {
float r = 0.0, delta = 0.0, alpha = 1.0;
vec2 cxy = 2.0 * gl_PointCoord - 1.0;
r = dot(cxy, cxy);
if (r > 1.0) {
discard;
}
gl_FragColor = color * alpha;
}`,

vert: `
precision mediump float;
attribute vec2 position;
attribute float pointWidth;

uniform float stageWidth;
uniform float stageHeight;

vec2 normalizeCoords(vec2 position) {
float x = position[0];
float y = position[1];

return vec2(
2.0 * ((x / stageWidth) - 0.5),
-(2.0 * ((y / stageHeight) - 0.5)));
}

void main () {
gl_PointSize = pointWidth;
gl_Position = vec4(normalizeCoords(position), 0, 1);
}`,

attributes: {
// There will be a position value for each point
// we pass in
position: function(context, props) {
return props.points.map(function(point) {
return [point.x, point.y];
});
},
// Now pointWidth is an attribute, as each
// point will have a different size.
pointWidth: function(context, props) {
return props.points.map(function(point) {
return point.size;
});
}
},

uniforms: {
color: function(context, props) {
// just to be a bit strange, oscillate the color a bit.
return [Math.cos(context.tick / 100), 0.304, 1.0, 1.0];
},
stageWidth: newRegl.context("drawingBufferWidth"),
stageHeight: newRegl.context("drawingBufferHeight")
},

count: function(context, props) {
// set the count based on the number of points we have
return props.points.length;
},
primitive: "points"
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function randomFromInterval(min, max) {
return Math.random() * (max - min) + min;
}
Insert cell
function randomIntFromInterval(min, max) {
return Math.floor(randomFromInterval(min, max));
}
Insert cell
function createData(dataCount) {
var data = [];
for (var i = 0; i < dataCount; i++) {
var datum = {
id: i,
speed: randomFromInterval(1, MAX_SPEED),
y: randomIntFromInterval(POINT_SIZE * 2, MAX_HEIGHT),
x: 0,
size: randomIntFromInterval(POINT_SIZE, POINT_SIZE * 3)
};

data.push(datum);
}
return data;
}
Insert cell
function updateData(data) {
data.forEach(function(datum) {
datum.x += datum.speed;
// reset x if its gone past max width
datum.x = datum.x > MAX_WIDTH ? 0 : datum.x;
});
}
Insert cell
Insert cell
points = createData(POINT_COUNT)
Insert cell
Insert cell
generateData = (num, min, max) => {
const arr = [];
for (let i = 0; i < num; i++) {
arr.push([randomFromInterval(min, max), randomIntFromInterval(min, max)]);
}
return arr;
}
Insert cell
myData = generateData(9000, 0, 10)
Insert cell
d3.extent(myData.map(arr => arr[0]))
Insert cell
d3.extent(myData.map(arr => arr[1]))
Insert cell
Insert cell
d3 = require('d3')
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