var width = 640, height = 300; var color = d3.scale.category20(); var force = d3.layout.force() .charge(-100) .linkDistance(5) .size([width, height]); var svg = d3.select("#chart").append("svg") .attr("width", width) .attr("height", height); var tooltip = svg.append("text") .attr('dy', '50px') .attr('dx', '10px') .attr('class', 'tooltip'); d3.json("songs.json", function(songs) { var json = {}; json.nodes = []; var ids = {}; for (var i = 0; i < songs.length; i++) { if (!ids.hasOwnProperty(songs[i].id)) { json.nodes.push(songs[i]); ids[songs[i].id] = json.nodes.length - 1; } } json.links = []; for (var i = 0; i < songs.length - 1; i++) { json.links.push({ source: ids[songs[i].id], target: ids[songs[i + 1].id] }); } force .nodes(json.nodes) .links(json.links) .start(); var link = svg.selectAll("line.link") .data(json.links) .enter().append("line") .attr("class", "link") .style("stroke-width", function(d) { return Math.sqrt(d.value); }); var node = svg.selectAll("circle.node") .data(json.nodes) .enter().append("circle") .attr("class", "node") .attr("r", 5) .style("fill", function(d) { return color(d.artist); }) .call(force.drag) .on('mouseover', function(d) { console.log('here'); tooltip.text(d.artist + ': ' + d.name); }) .on('mouseout', function(d) { tooltip.text(''); }); node.append("title") .text(function(d) { return d.artist + ': ' + d.name; }); force.on("tick", function() { 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; }); }); });