{
const graph = new graphlib.Graph()
.setGraph({})
.setDefaultEdgeLabel(() => ({}));
graph.setNode(0, { label: "Enrollment", class: "type-enrollment" });
graph.setNode(1, {
label: "Randomization (2:1)",
class: "type-randomization"
});
graph.setNode(2, { label: "Cohort 1", class: "type-cohort-1" });
graph.setNode(3, { label: "Cohort 2", class: "type-cohort-2" });
graph.setNode(4, {
label: "Study Completion",
class: "type-study-completion"
});
graph.nodes().forEach(v => {
const node = graph.node(v);
node.rx = node.ry = 5;
});
graph.setEdge(0, 1);
graph.setEdge(1, 2);
graph.setEdge(1, 3);
graph.setEdge(2, 4);
graph.setEdge(3, 4);
const svg = d3.select(html`<svg width=${width} height=600>`);
yield svg.node();
const g = svg
.append("g")
.call(new dagred3.render(), graph)
.attr("transform", `translate(${(width - graph.graph().width) / 2},20)`);
svg.attr("height", graph.graph().height + 40);
yield svg.node();
const radius = 7.5;
const states = Object.keys(graph._nodes).map(key => graph._nodes[key]);
const top = { ...states[0] };
top.y = -40 - radius;
const bottom = { ...states[states.length - 1] };
bottom.y = graph.graph().height + 40 + radius;
states.unshift(top);
states.push(bottom);
let stateIndex = 0;
const nodeData = d3.range(0, 3).map((_, i) => {
const datum = {};
datum.states = states
.filter((state, j) => (i % 3 ? j !== 4 : j !== 3))
.map(state => ({ ...state }));
datum.state = datum.states[stateIndex];
return datum;
});
const nStates = d3.max(nodeData, d => d.states.length);
const forceSimulation = d3
.forceSimulation()
.nodes(nodeData)
.force('x', d3.forceX(d => d.state.x))
.force('y', d3.forceY(d => d.state.y))
.force('collide', d3.forceCollide().radius(radius + 3));
const nodes = g
.selectAll('g.node--circle')
.data(nodeData)
.join('g')
.attr('class', 'node--circle')
.call(drag(forceSimulation));
nodes
.append('circle')
.attr('r', radius)
.style('fill', 'steelblue')
.style('fill-opacity', .5)
.style('stroke', 'steelblue')
.style('stroke-opacity', 1);
forceSimulation.on('tick', () => {
nodes.attr('transform', d => `translate(${d.x},${d.y})`);
});
yield svg.node();
const interval = d3.interval(() => {
if (stateIndex === 0) nodes.style('display', 'none');
else nodes.style('display', null);
nodeData.forEach(d => {
d.state = d.states[stateIndex];
});
forceSimulation
.alpha(1)
.force('x', d3.forceX(d => d.state.x))
.force('y', d3.forceY(d => d.state.y))
.restart();
stateIndex++;
if (stateIndex > nStates - 1) stateIndex = 0;
}, 1000);
}