Published
Edited
Aug 23, 2021
Fork of Arcs
1 fork
Insert cell
Insert cell
chart = {
var margin = {top: 50, right: 30, bottom: 50, left: 30};
var w = width - margin.left - margin.right;
var h = height - margin.top - margin.bottom;
const svg = d3.select(DOM.svg(width, height))
.attr("shape-rendering", "geometric-precision");

var padding = 2,
radius = 3;

//var graph = graph8am; //fish
//var graph = graphRealWorld; //fish
var xAxisTicks = graph.nodes.map(function(xTick) {
return xTick.id;
});
var x = d3.scalePoint()
.domain(xAxisTicks)
.range([margin.left, w + margin.right]);

var xAxis = d3.axisBottom(x);

var colorScale = d3.scaleOrdinal(d3.schemeCategory10)
.domain(xAxisTicks);
svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + h + ')')
.call(xAxis);

var nodes = [], index = 0, clusters = {};

graph.links.forEach(link => {
for(var i=0; i < link.opens; i++) {
nodes.push({
index: index,
source: link.source,
target: link.target,
cluster: link.source + '::' + link.target,
x: x(link.target),
//fx: x(link.target),
y: margin.top + (h/2)
});
if(!clusters[link.source + '::' + link.target]) {
clusters[link.source + '::' + link.target] = nodes[nodes.length-1];
}

index++;
}
});

var simulation = d3.forceSimulation(nodes)
.force('x', d3.forceX(function(d) { return x(d.target); }).strength(1))
.force('y', d3.forceY(h / 2))
.force('collide', d3.forceCollide(4))
//.force('cluster', cluster().strength(0.2))
//.on('tick', layoutTick)
.stop();

/*
var simulation = d3.forceSimulation(nodes)
.force('y', d3.forceY(250))
.force('collide', d3.forceCollide().radius(radius + padding))
.force('manyBody', d3.forceManyBody().strength(-10))
.stop();
*/

for (var i = 0; i < 150; ++i) simulation.tick();

var circle = svg.selectAll('circle')
.data(nodes)
.enter().append('circle')
.style('fill', function(d) { return colorScale(d.source); })
.attr('cx', function(d) { return d.x } )
.attr('cy', function(d) { return d.y } )
.attr('r', radius)
.style('opacity', 0.6);
//.on('mouseover', tip.show)
//.on('mouseout', tip.hide)

function layoutTick() {
circle
.attr('cx', function(d) { return d.x } )
.attr('cy', function(d) { return d.y } )
.attr('r', radius)
}
//Move d to be adjacent to the cluster node.
function cluster() {
var nodes,
strength = 0.1;

function force(alpha) {
// scale + curve alpha value
alpha *= strength * alpha;

nodes.forEach(function(d) {
var cluster = clusters[d.cluster];
if (cluster.index === d.index) return;

console.log('---------------'); //fish
console.log('d:', d); //fish
console.log('cluster:', cluster); //fish

let x = d.x - cluster.x,
y = d.y - cluster.y,
l = Math.sqrt(x * x + y * y),
r = d.radius + cluster.radius;

if(l != r) {
l = (l - r) / l * alpha;
d.x -= x *= l;
d.y -= y *= l;
cluster.x += x;
cluster.y += y;
}
});
}

force.initialize = function (_) {
nodes = _;
}

force.strength = _ => {
strength = _ == null ? strength : _;
return force;
};

return force;
}

return svg.node()
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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