chart = {
const wtcut = 0;
const links = data.links.map(d => Object.create(d));
const nodes = data.nodes.map(d => Object.create(d));
const simulation = d3.forceSimulation(nodes)
.force('x', d3.forceX().strength(2).x(d =>width/(maxLayer+1) * (d.LayerNum+1)))
.force("link", d3.forceLink(links).id(d => d.id))
.force("charge", d3.forceManyBody().strength(-250))
.force("center", d3.forceCenter(width / 2, height / 2));
const svg = d3.select(DOM.svg(width, height));
const link = svg.append("g")
.selectAll("line")
.data(links)
.join("line")
.attr("class", "link")
.attr("stroke", d => d.weight> 0? "#FF374C":"#6495ED")
.attr("stroke-opacity", d => Math.abs(d.weight)/maxwt)
.attr("stroke-width", d => Math.abs(d.weight)>wtcut? Math.abs(d.weight)*2 : 0);
const node = svg.append("g")
.attr("stroke", "#fff")
.attr("stroke-width", 1.5)
.selectAll("circle")
.data(nodes)
.join("circle")
.attr("r", d => Math.abs(d.valueScaled)*10+2)
.attr("fill", d => d.valueScaled> 0? "#FF8C00":"#00CED1")
.call(drag(simulation));
const bar = svg.append("g")
bar.append("rect")
.attr(x)
var x = d3.scaleLinear()
.domain([-0.1, 1.1])
.range([100, width-100]);
var brush = d3.brushX()
.extent([[100, height*9/10 - 30], [width-100, height*9/10]])
.on("start brush", brushed);
const axis = bar.append("g")
.attr("transform", "translate(0," + height*9/10 + ")")
.call(d3.axisBottom(x));
var dot = bar.append("g")
.selectAll(".dot")
.data(links)
.enter()
.append("circle")
.attr("class","dot")
.attr("cx", d=>x(Math.abs(d.weight)/maxwt))
.attr("cy", d => d.weight> 0? height*9/10 -10 : height*9/10 -20)
.attr("fill", d => d.weight>= 0? "#FF374C":"#6495ED")
.attr("r", 1.5)
.attr("fill-opacity", d=> Math.abs(d.weight)/maxwt);
bar.append("g")
.call(brush)
.call(brush.move, [x(0),x(1.1)])
.selectAll(".overlay")
.each(function(d) { d.type = "selection"; }) // Treat overlay interaction as move.
.on("mousedown touchstart", brushclicked); // Recenter before brushing.
function brushclicked() {
var cx = d3.mouse(this)[0];
d3.select(this.parentNode).call(brush.move, cx > x(1.1) ? [x(0), x(1.1)] : cx < x(-0.1) ? [x(-0.1), x(1.1)] : [cx, x(1.1)]);
}
function brushed() {
var extent = d3.event.selection;
d3.selectAll(".link").attr("stroke-width", function(d) {
if(extent[0] <= x(Math.abs(d.weight)/maxwt) && x(Math.abs(d.weight)/maxwt) <= extent[1])
{
return Math.abs(d.weight)*2;
}
else
{
return 0;
}
});
}
node.append("title")
.text(d => ['layer:'+d.LayerNum, ' node:'+d.NodeNum, ' value:'+d.value]);
simulation.on("tick", () => {
link
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
node
.attr("cx", d => d.x)
.attr("cy", d => d.y);
});
invalidation.then(() => simulation.stop());
return svg.node();
}