setup = {
const margin = { top: 120, right: 0, bottom: 10, left: 120 }
const leafSet = new Set();
graph.links.map(d => leafSet.add(d.source));
const nodeIds = Array.from(leafSet);
const parentSet = new Set();
graph.links.map(d => parentSet.add(d.target));
const parentIds = Array.from(parentSet);
const height = nodeIds.length * 10
const width = parentIds.length * 10
const y = d3
.scaleBand()
.domain(nodeIds)
.range([0, height]),
x = d3
.scaleBand()
.domain(parentIds)
.range([0, width]),
z = d3
.scaleLinear()
.domain([0, 4])
.clamp(true),
c = d3.scaleOrdinal(d3.range(10), d3.schemeCategory10);
const svg = d3
.create("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
const g = svg
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
g.append("rect")
.style("fill", "#eee")
.attr("width", width)
.attr("height", height);
const matrix = graph.links
.flatMap(({ source, target, value }) => [
[source, target, value]//,
//[target, source, value]
])
//.concat(nodeIds.map(i => [i, i]));
const labels = g
.append("g")
.style("font-size", "8px")
.style("font-family", "sans-serif");
const columns = labels
.append("g")
.selectAll()
.data(parentIds)
.join("g")
.attr("transform", "rotate(-90)")
.append("g");
columns
.append("line")
.attr("x2", -height)
.style("stroke", "white");
columns
.append("text")
.attr("dx", 2)
.attr("dy", y.bandwidth() / 2 + 2)
.text(i => graph.nodes[i].name);
const rows = labels
.append("g")
.selectAll()
.data(nodeIds)
.join("g");
rows
.append("line")
.attr("x2", width)
.style("stroke", "white");
rows
.append("text")
.attr("text-anchor", "end")
.attr("dx", -2)
.attr("dy", x.bandwidth() / 2 + 2)
.text(i => graph.nodes[i].name);
const rects = g
.append("g")
.attr("transform", "translate(1,1)")
.selectAll()
.data(matrix)
.join("rect")
.attr("width", x.bandwidth() - 2)
.attr("height", y.bandwidth() - 2)
.attr("fill", ([s, t]) =>
graph.nodes[s].group === graph.nodes[t].group
? c(graph.nodes[t].group)
: "black"
)
.attr("fill-opacity", ([, , v]) => z(v));
let prev;
update(graph.nodes.map(d => +d.id));
function update(permutation) {
x.domain(permutation.filter(function(d) {return parentSet.has(d)}));
y.domain(permutation.filter(function(d) {return leafSet.has(d)}));
const delayx = prev ? i => x(i) * 4 : 0;
const delayy = prev ? i => y(i) * 4 : 0;
const delay2 = prev ? ([i]) => y(i) * 4 : 0;
const duration = prev ? 1500 : 0;
columns
.transition()
.delay(delayx)
.duration(duration)
.attr("transform", i => `translate(0, ${x(i)})`);
rows
.transition()
.delay(delayy)
.duration(duration)
.attr("transform", i => `translate(0, ${y(i)})`);
rects
.transition()
//.delay(delay2)
.duration(duration)
.attr("x", ([, t]) => x(t))
.attr("y", ([s]) => y(s));
prev = permutation;
return permutation;
}
return Object.assign(svg.node(), { update });
}