// The original idea for this visualization came from // [Multi-Foci Force Layout](https://bl.ocks.org/mbostock/1021841). // Much information is also available in the // [D3 Force Layout API](https://github.com/mbostock/d3/wiki/Force-Layout). // load data set d3.json('zchampions.json', function(error, champions) { // draw button to disable visualizing links var controls = d3.select('body') .append('div'); var button = controls.append('input') .attr('type', 'submit') .attr('value', 'Show Links') .attr('margin', '5px'); button.show = true; controls.append('span') .style('margin', '0px 0px 0px 10px') .attr('class', 'title-text-0') .append('b') .text('Try dragging nodes around!'); if (error) { throw error; } // prepare dataset var dataset = new Dataset(champions); // boundaries var margin = { top: 75, right: 120, bottom: 20, left: 120 }; var width = 1000 - margin.right - margin.left; var height = 850 - margin.top - margin.bottom; // prepare force layout // refer to [force api](https://github.com/mbostock/d3/wiki/Force-Layout#drag) var force = d3.layout.force() .nodes(dataset.getNodes()) .links(dataset.getLinks()) .size([ width, height ]) .linkStrength(1.0) .friction(0.9) // separate the nodes by radius for visibility .linkDistance(function(link) { return link.source.radius + link.target.radius + 75; }) .charge(-10) .gravity(0.1) .theta(0.8) .alpha(0.1) .on('tick', update) .start(); // prepare svg element var svg = d3.select('body') .append('svg') .attr('width', width + margin.right + margin.left) .attr('height', height + margin.top + margin.bottom) .append('g') .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); // nodes now have updated position values from force layout var nodes = svg.selectAll('.node') .data(dataset.getNodes()) .enter() .append('circle') .attr('class', '.node') .attr('cx', function(d) { return d.x; }) .attr('cy', function(d) { return d.y; }) .attr('r', function(d) { return d.radius; }) .style('fill', function(d, i) { return d.color; }) .style('stroke', function(d, i) { return d3.rgb(dataset.colorScale(i)).darker(2); }) // bind a behavior to nodes to allow interactive dragging // [see](https://github.com/mbostock/d3/wiki/Force-Layout#drag) .call(force.drag); var labels = svg.selectAll('.labels') .data(dataset.getNodes()) .enter() .append('text') .attr('class', 'data-text-0') .text(function(d) { return d.count; }) .attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'; }); var links = svg.selectAll('.link') .data(dataset.getLinks()) .enter() .append("line"); function update(e) { nodes.attr('cx', function(d) { return d.x; }) .attr('cy', function(d) { return d.y; }); links.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; }); labels.attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'; }); } // draw legend var legend = new Legend(svg); legend.draw(dataset.getNodes()); // set up button button.on('click', function() { if (button.show) { links.style('stroke', 'black'); } else { links.style('stroke', 'none'); } button.show = !button.show; }); console.log(dataset.getNodes()); });