Published
Edited
Jun 17, 2020
Importers
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof graph = {
const edges = linkEdges(data.nodes, data.edges);
const config = { width, height, bb };

const svg = this ? this.value : d3.create('svg');

svg
.transition()
.duration(svgDuration)
.attr('width', config.width)
.attr('height', config.height)
.attr('viewBox', config.bb);

d3render(svg, [
{
append: "style",
key: "styles",
text: styles
},
EdgeNodeComponent(data.nodes, edges)
]);

svg.node().value = svg;
return svg.node();
}
Insert cell
Insert cell
Insert cell
EdgeNodeComponent = DefaultEdgeNodeComponent
Insert cell
DefaultEdgeNodeComponent = (nodes, edges) => ({
append: "g",
key: "edge-node",
duration: edgenodeDuration,
children: [
{
append: 'g',
key: "edges",
children: _.map(edges, EdgeComponent)
},
{
append: "g",
key: "nodes",
children: _.map(nodes, NodeComponent)
}
]
})
Insert cell
Insert cell
EdgeComponent = DefaultEdgeComponent
Insert cell
DefaultEdgeComponent = e => ({
append: 'path',
class: 'edge',
d: `M ${e.source.x} ${e.source.y} L ${e.target.x} ${e.target.y}`,
duration: edgeDuration
})
Insert cell
Insert cell
NodeComponent = DefaultNodeComponent
Insert cell
DefaultNodeComponent = n => ({
append: "g",
class: "node",
key: n.index.toString(),
style: {
transform: {
enter: `translate3d(${n.x - n.width / 2}px, ${n.y - n.height / 2}px, 0)`,
exit: `translate3d(${width / 2}px, ${height / 2}px, 0)`
}
},
opacity: { enter: 1, exit: 0 },
children: [
{
append: "rect",
width: n.width,
height: n.height,
duration: nodeDuration
},
{
append: "text",
text: n.label,
fontSize: "10px",
textAnchor: "middle",
dominantBaseline: "middle",
dy: n.height / 2,
dx: n.width / 2,
duration: nodeDuration
}
],
duration: nodeDuration
})
Insert cell
Insert cell
viewof duration = slider({
title: "Animation Duration",
min: 50,
max: 2000,
step: 1,
value: 250,
description: "used by default by all durations"
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
randomNode = i => ({
index: i,
label: "Node " + i,
width: Math.floor(Math.random() * 20) + 50,
height: Math.floor(Math.random() * 20) + 20,
x: Math.floor(Math.random() * width),
y: Math.floor(Math.random() * height)
})
Insert cell
function linkEdges(nodes, edges) {
const indexNodes = _.keyBy(nodes, "index");
return _.map(edges, ({ source, target, ...rest }) => ({
...rest,
source: indexNodes[source],
target: indexNodes[target]
}));
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
import { slider } from "@jashkenas/inputs"
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