block by vanshady a60972c1332a6cc87588a7157212c578

Smiley Faces Force Layout Graph

Full Screen

index.html

<!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", "//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 //bl.ocks.org/eesur/be2abfb3155a38be4de4 */
    </script>
</body>
</html>

smiley.json

{
   "children": [
  {
   "children": [
    {
      "size": 1
    },
    {
      "size": 1
    },
    {
      "size": 1
    },
    {
      "size": 1
    },
    {
      "size": 1
    },
    {
      "size": 1
    },
    {
      "size": 1
    },
    {
      "size": 1
    },
    {
      "size": 1
    }
  ]
  },
  {
   "children": [
    {
      "size": 1
    },
    {
      "size": 1
    },
    {
      "size": 1
    },
    {
      "size": 1
    },
    {
      "size": 1
    },
    {
      "size": 1
    },
    {
      "size": 1
    }
   ]
  },
  {
   "children": [
    {
      "size": 1
    },
    {
      "size": 1
    },
    {
      "size": 1
    },
    {
      "size": 1
    },
    {
      "size": 1
    },
    {
      "size": 1
    }
   ]
  }  
 ]
}