Built with blockbuilder.org
forked from shimizu's block: D3 v4 - force layout
| license: gpl-3.0 |
Built with blockbuilder.org
forked from shimizu's block: D3 v4 - force layout
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <meta http-equiv="X-UA-Compatible" content="IE=edge"/> | |
| <title>D3 v4 - force layout</title> | |
| <style> | |
| html, body, #graph { | |
| width: 900px; | |
| height: 500px; | |
| } | |
| svg { | |
| background: lightblue; | |
| width: 500px; | |
| height: 500px; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="graph"></div> | |
| <script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.1.1/d3.js"></script> | |
| <script> | |
| !(function(){ | |
| "use strict" | |
| var width,height | |
| var chartWidth, chartHeight | |
| var margin | |
| var svg = d3.select("#graph").append("svg") | |
| var chartLayer = svg.append("g").classed("chartLayer", true) | |
| main() | |
| function main() { | |
| var range = 100 | |
| var data = { | |
| nodes:d3.range(0, range).map(function(d){ return {label: "l"+d ,r:~~d3.randomUniform(8, 28)()}}), | |
| links:d3.range(0, range).map(function(){ return {source:~~d3.randomUniform(range)(), target:~~d3.randomUniform(range)()} }) | |
| } | |
| setSize(data) | |
| drawChart(data) | |
| } | |
| function setSize(data) { | |
| let bound = document.querySelector("svg") | |
| .getBoundingClientRect(); | |
| width = bound.width; | |
| height = bound.height; | |
| margin = {top:0, left:0, bottom:0, right:0 } | |
| chartWidth = width - (margin.left+margin.right) | |
| chartHeight = height - (margin.top+margin.bottom) | |
| svg.attr("width", width).attr("height", height) | |
| chartLayer | |
| .attr("width", chartWidth) | |
| .attr("height", chartHeight) | |
| .attr("transform", "translate("+[margin.left, margin.top]+")") | |
| } | |
| function drawChart(data) { | |
| function edgeForce(axis, origin, strength) { | |
| var nodes; | |
| function force(alpha) { | |
| nodes.forEach(function(node) { | |
| Math.max(Math.abs(origin - node[axis]), node.r) | |
| var delta = strength / (origin - node[axis]) * alpha; | |
| var repulsion = node.r * strength / 10000 | |
| node[axis] -= delta; | |
| }) | |
| } | |
| force.initialize = function(_) { | |
| nodes = _; | |
| } | |
| return force; | |
| } | |
| var simulation = d3.forceSimulation() | |
| //.force("link", d3.forceLink().id(function(d) { return d.index })) | |
| .force("collide",d3.forceCollide( function(d){return d.r + 4 }).iterations(16) ) | |
| //.force("charge", d3.forceManyBody()) | |
| .force("center", d3.forceCenter(chartWidth / 2, chartHeight / 2)) | |
| //.force("y", d3.forceY(0)) | |
| //.force("x", d3.forceX(0)) | |
| .force('edge-left', edgeForce('x', 0, 1000)) | |
| .force('edge-right', edgeForce('x', chartWidth, 1000)) | |
| .force('edge-top', edgeForce('y', 0, 1000)) | |
| .force('edge-bottom', edgeForce('y', chartHeight, 1000)) | |
| var link = svg.append("g") | |
| .attr("class", "links") | |
| .selectAll("line") | |
| .data(data.links) | |
| .enter() | |
| .append("line") | |
| .attr("stroke", "black") | |
| var node = svg.append("g") | |
| .attr("class", "nodes") | |
| .selectAll("circle") | |
| .data(data.nodes) | |
| .enter().append("circle") | |
| .attr("r", function(d){ return d.r }) | |
| .call(d3.drag() | |
| .on("start", dragstarted) | |
| .on("drag", dragged) | |
| .on("end", dragended)); | |
| var ticked = 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; }); | |
| } | |
| simulation | |
| .nodes(data.nodes) | |
| .on("tick", ticked); | |
| simulation.force("link") | |
| .links(data.links); | |
| 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; | |
| } | |
| } | |
| }()); | |
| </script> | |
| </body> | |
| </html> |