Public
Edited
May 1, 2024
3 forks
52 stars
Insert cell
Insert cell
container = html `<div style="height:450px;"></div>`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
defaultProps = {
return {
// Frequency of the running light
getFrequency: {type: 'accessor', value: 1},
// Speed of the running light
animationSpeed: {type: 'number', min: 0, value: 1},
// Size of the blob
tailLength: {type: 'number', min: 0, value: 1}
}
}
Insert cell
layer0 = {
const {ArcLayer} = deck;
// Our custom layer class
class AnimatedArcLayer extends ArcLayer {
}
AnimatedArcLayer.layerName = 'AnimatedArcLayer';
AnimatedArcLayer.defaultProps = defaultProps;

return new AnimatedArcLayer({
id: `arc-${Date.now()}`,
data,
getTargetColor: [0, 200, 255],
getSourceColor: d => [255, 200 - d.distance / 50, 0],
getFrequency: d => d.routes
});
}
Insert cell
Insert cell
layer0.props.tailLength
Insert cell
Insert cell
layer1 = {
const {ArcLayer} = deck;
// Our custom layer class
class AnimatedArcLayer extends ArcLayer {

initializeState(params) {
super.initializeState(params);
this.getAttributeManager().addInstanced({
instanceFrequency: {
size: 1,
accessor: 'getFrequency',
defaultValue: 1
},
});
}
draw(opts) {
this.state.model.setUniforms({
tailLength: this.props.tailLength,
animationSpeed: this.props.animationSpeed,
timestamp: Date.now() % 86400000
});
super.draw(opts);
// By default, the needsRedraw flag is cleared at each render. We want the layer to continue
// refreshing.
this.setNeedsRedraw();
}
}
AnimatedArcLayer.layerName = 'AnimatedArcLayer';
AnimatedArcLayer.defaultProps = defaultProps;

return new AnimatedArcLayer({
id: `arc-${Date.now()}`,
data,
getTargetColor: [0, 200, 255],
getSourceColor: d => [255, 200 - d.distance / 50, 0],
getFrequency: d => d.routes
});
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
fsColorFilter = `
float tripDuration = vArcLength / animationSpeed;
float flightInterval = 1.0 / vFrequency;
float r = mod(geometry.uv.x, flightInterval);

// Head of the trip (alpha = 1.0)
float rMax = mod(fract(timestamp / tripDuration), flightInterval);
// Tail of the trip (alpha = 0.0)
float rMin = rMax - tailLength / vArcLength;
// Two consecutive trips can overlap
float alpha = (r > rMax ? 0.0 : smoothstep(rMin, rMax, r)) + smoothstep(rMin + flightInterval, rMax + flightInterval, r);
if (alpha == 0.0) {
discard;
}
color.a *= alpha;
`
Insert cell
layer2 = {
const {ArcLayer} = deck;
// Our custom layer class
class AnimatedArcLayer extends ArcLayer {
getShaders() {
const shaders = super.getShaders();
shaders.inject = {
'vs:#decl': vsDeclaration,
'vs:#main-end': vsMain,
'fs:#decl': fsDeclaration,
'fs:DECKGL_FILTER_COLOR': fsColorFilter
};
return shaders;
}

initializeState(params) {
super.initializeState(params);
this.getAttributeManager().addInstanced({
instanceFrequency: {
size: 1,
accessor: 'getFrequency',
defaultValue: 1
},
});
}
draw(opts) {
this.state.model.setUniforms({
tailLength: this.props.tailLength,
animationSpeed: this.props.animationSpeed,
timestamp: (Date.now() / 1000) % 86400
});
super.draw(opts);
// By default, the needsRedraw flag is cleared at each render. We want the layer to continue
// refreshing.
this.setNeedsRedraw();
}
}
AnimatedArcLayer.layerName = 'AnimatedArcLayer';
AnimatedArcLayer.defaultProps = defaultProps;

const layer = new AnimatedArcLayer({
id: `arc-${Date.now()}`,
data,
getTargetColor: [0, 200, 255],
getSourceColor: d => [255, 200 - d.distance / 50, 0],
getFrequency: d => d.routes,
animationSpeed: 3,
tailLength: 5
});
deckgl.setProps({layers: [layer]});
return layer;
}
Insert cell
Insert cell
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