Here is the HTML:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> <title> graph </title> <script src='https://d3js.org/d3.v4.min.js'></script> <link href='style.css' rel='stylesheet'> </head> <body> <div id='container' class='svg-container'></div> <script src='script.js'></script> </body> </html>
Here is the CSS:
.svg-container { display: inline-block; position: relative; width: 100%; padding-bottom: 50%; vertical-align: top; overflow: hidden; } .svg-content { display: inline-block; position: relative; top: 0; left: 0; } .links line { stroke: #000000; stroke-opacity: 0.4; } .nodes circle { stroke: #000000; stroke-width: 1.5px; }
Here is the Javascript/D3:
// adapted from: // https://bl.ocks.org/mbostock/4062045 // Mike Bostock’s Block 4062045 var width = 960 var height = 600 var svg = d3.select('div#container') .append('svg') .attr('preserveAspectRatio', 'xMinYMin meet') .attr('viewBox', '0 0 960 600') .classed('svg-container', true); var simulation = d3.forceSimulation() .force('link', d3.forceLink().id(function(d) { return d.id; })) .force('charge', d3.forceManyBody().strength(-800)) .force('center', d3.forceCenter(width / 2, height / 2)); d3.json('network.json', function(error, graph) { if (error) throw error; var link = svg.append('g') .attr('class', 'links') .selectAll('line') .data(graph.links) .enter().append('line') // // best choice for relative importance of relationships to characters in the strip .attr('stroke-width', function(d) { return 22 * Math.sqrt(d.proportion_coappearances); }); // // best choice for showing prominence of relationships in the strip //.attr('stroke-width', function(d) { return (d.number_coappearances) / 60; }); // // alternatives //.attr('stroke-width', function(d) { return 35 * (d.proportion_coappearances); }); //.attr('stroke-width', function(d) { return 20 * Math.cbrt(d.proportion_coappearances); }); //.attr('stroke-width', function(d) { return Math.sqrt(d.number_coappearances) / 1; }); var node = svg.append('g') .attr('class', 'nodes') .selectAll('circle') .data(graph.nodes) .enter().append('circle') .attr('fill', function(d) { return d3.color(d.colors); }) //.attr('r', function(d) { return d.n_appears / 150; }) .attr('r', function(d) { return 3 * Math.log(d.n_appears); }) //.attr('r', function(d) { return Math.sqrt(d.n_appears) / 3; }) .on('mouseover', onMouseover) .call(d3.drag() .on('start', dragstarted) .on('drag', dragged) .on('end', dragended)); node.append('title') .text(function(d) { return d.id; }); simulation .nodes(graph.nodes) .on('tick', ticked); simulation.force('link') .links(graph.links); function ticked() { link .attr('x1', function(d) { return d.source.x; }) .attr('y1', function(d) { return d.source.y; }) .attr('x2', function(d) { return d.target.x; }) .attr('y2', function(d) { return d.target.y; }); node .attr('cx', function(d) { return d.x; }) .attr('cy', function(d) { return d.y; }); } }); function dragstarted(d) { if (!d3.event.active) simulation.alphaTarget(0.3).restart(); d.fx = d.x; d.fy = d.y; } function dragged(d) { d.fx = d3.event.x; d.fy = d3.event.y; } function dragended(d) { if (!d3.event.active) simulation.alphaTarget(0); d.fx = null; d.fy = null; } function onMouseover(elemData) { // adapted from: // https://jsfiddle.net/e8kq7bdp/1/ d3.select('svg').selectAll('circle') .select( function(d) { return d===elemData?this:null;}) }