D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
vanshady
Full window
Github gist
Smiley Faces Force Layout Graph
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Smiley Faces Force Layout Graph</title> <script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script> <style> body { line-height: 160%; font-size: 16px; margin: 0; } path.link { fill: none; stroke-width: 2px; } .node:not(:hover) .nodetext { display: none; } a:link { color: #EE3124; text-decoration: none; } a:visited { color: #EE3124; } a:hover { color: #A4CD39; text-decoration: underline; } a:active { color: #EE3124; } </style> </head> <body> <!-- container for force layout visualisation --> <section id="vis"></section> <script> // rest of vars var w = window.innerWidth, h = window.innerHeight, maxNodeSize = 50, x_browser = 20, y_browser = 25, root; var vis; var force = d3.layout.force(); vis = d3.select("#vis").append("svg").attr("width", w).attr("height", h); d3.json("smiley.json", function(json) { root = json; root.fixed = true; root.x = w / 2; root.y = h / 4; // Build the path var defs = vis.insert("svg:defs") .data(["end"]); defs.enter().append("svg:path") .attr("d", "M0,-5L10,0L0,5"); update(); }); function update() { var nodes = flatten(root), links = d3.layout.tree().links(nodes); // Restart the force layout. force.nodes(nodes) .links(links) .gravity(0.05) .charge(-1500) .linkDistance(100) .friction(0.5) .linkStrength(function(l, i) { return 1; }) .size([w, h]) .on("tick", tick) .start(); var path = vis.selectAll("path.link") .data(links, function(d) { return d.target.id; }); path.enter().insert("svg:path") .attr("class", "link") .style("stroke", "#eee"); // Exit any old paths. path.exit().remove(); // Update the nodes… var node = vis.selectAll("g.node") .data(nodes, function(d) { return d.id; }); // Enter any new nodes. var nodeEnter = node.enter().append("svg:g") .attr("class", "node") .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }) .on("click", click) .call(force.drag); // Append a circle nodeEnter.append("svg:circle") .attr("r", function(d) { return Math.sqrt(d.size) / 10 || 4.5; }) .style("fill", "#eee"); // Append images var images = nodeEnter.append("svg:image") .attr("xlink:href", "https://fc08.deviantart.net/fs71/f/2013/354/8/7/blinking_smiley__animated__by_mondspeer-d6ylwn3.gif") .attr("x", function(d) { return -25; }) .attr("y", function(d) { return -25; }) .attr("height", 50) .attr("width", 50); // make the image grow a little when mouse over var setEvents = images .on('mouseenter', function() { // select element in current context d3.select(this) .transition() .attr("x", function(d) { return -60; }) .attr("y", function(d) { return -60; }) .attr("height", 100) .attr("width", 100); }) // set back .on('mouseleave', function() { d3.select(this) .transition() .attr("x", function(d) { return -25; }) .attr("y", function(d) { return -25; }) .attr("height", 50) .attr("width", 50); }); // Append HaHa on roll over next to the node as well nodeEnter.append("text") .attr("class", "nodetext") .attr("x", x_browser) .attr("y", y_browser + 15) .text("HaHa"); // Exit any old nodes. node.exit().remove(); // Re-select for update. path = vis.selectAll("path.link"); node = vis.selectAll("g.node"); function tick() { path.attr("d", function(d) { var dx = d.target.x - d.source.x, dy = d.target.y - d.source.y, dr = Math.sqrt(dx * dx + dy * dy); return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y; }); node.attr("transform", nodeTransform); } } function nodeTransform(d) { d.x = Math.max(maxNodeSize, Math.min(w - (d.imgwidth / 2 || 16), d.x)); d.y = Math.max(maxNodeSize, Math.min(h - (d.imgheight / 2 || 16), d.y)); return "translate(" + d.x + "," + d.y + ")"; } /** * Toggle children on click. */ function click(d) { if (d.children) { d._children = d.children; d.children = null; } else { d.children = d._children; d._children = null; } update(); } /** * Returns a list of all nodes under the root. */ function flatten(root) { var nodes = []; var i = 0; function recurse(node) { if (node.children) node.children.forEach(recurse); if (!node.id) node.id = ++i; nodes.push(node); } recurse(root); return nodes; } /* thanks to https://bl.ocks.org/eesur/be2abfb3155a38be4de4 */ </script> </body> </html>
https://d3js.org/d3.v3.min.js