D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
MTClass
Full window
Github gist
Scatter Plot Chart // source http://jsbin.com/xuwotan
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=1,maximum-scale=1"/> <title>Custom Force Manipulation</title> <link rel="stylesheet" type="text/css" href="../../css/styles.css"/> <script type="text/javascript" src="../../lib/d3.js"></script> <script src="https://d3js.org/d3.v4.min.js"></script> <style type="text/css"> .touch{ fill-opacity: .2 } </style> </head> <body> <script type="text/javascript"> var svg = d3.select("body").append("svg"), colors = d3.scaleOrdinal(d3.schemeCategory20c), r = 4.5, w = 1290, h = 800; svg.attr("width", w).attr("height", h); var force = d3.forceSimulation() .velocityDecay(0.8) .alphaDecay(0) .force("charge", d3.forceManyBody().strength(-30)) .force("x", d3.forceX(w / 2)) .force("y", d3.forceY(h / 2)) .force("collision", d3.forceCollide(r + 0.5).strength(1)); var nodes = [], centers = []; for (var i = 0; i < 5; ++i) { for (var j = 0; j < 50; ++j) { nodes.push({ x: w / 2 + offset(), y: h / 2 + offset(), color: colors(i), // <-A type: i // <-B }); } } force.nodes(nodes); function offset() { return Math.random() * 100; } function boundX(x) { return x > (w - r) ? (w - r): (x > r ? x : r); } function boundY(y){ return y > (h - r) ? (h - r) : (y > r ? y : r); } svg.selectAll("circle") .data(nodes).enter() .append("circle") .attr("class", "node") .attr("cx", function (d) {return d.x;}) .attr("cy", function (d) {return d.y;}) .attr("fill", function(d){return d.color;}) .attr("r", 1e-6) .transition() .attr("r", r); force.on("tick", function() { var k = 0.1; nodes.forEach(function(node) { var center = centers[node.type]; if(center){ node.x += (center[0] - node.x) * k; // <-C node.y += (center[1] - node.y) * k; // <-D } }); svg.selectAll("circle") .attr("cx", function (d) {return boundX(d.x);}) .attr("cy", function (d) {return boundY(d.y);}); }); d3.select("body") .on("touchstart", touch) .on("touchend", touch); function touch() { d3.event.preventDefault(); centers = d3.touches(svg.node()); var g = svg.selectAll("g.touch") .data(centers, function (d) { return d.identifier; }); g.enter() .append("g") .attr("class", "touch") .attr("transform", function (d) { return "translate(" + d[0] + "," + d[1] + ")"; }) .append("circle") .attr("class", "touch") .attr("fill", function(d){return colors(d.identifier);}) .transition() .attr("r", 50); g.exit().remove(); } </script> <script id="jsbin-source-html" type="text/html"> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=1,maximum-scale=1"/> <title>Custom Force Manipulation</title> <link rel="stylesheet" type="text/css" href="../../css/styles.css"/> <script type="text/javascript" src="../../lib/d3.js"><\/script> <script src="https://d3js.org/d3.v4.min.js"><\/script> <style type="text/css"> .touch{ fill-opacity: .2 } </style> </head> <body> <script type="text/javascript"> var svg = d3.select("body").append("svg"), colors = d3.scaleOrdinal(d3.schemeCategory20c), r = 4.5, w = 1290, h = 800; svg.attr("width", w).attr("height", h); var force = d3.forceSimulation() .velocityDecay(0.8) .alphaDecay(0) .force("charge", d3.forceManyBody().strength(-30)) .force("x", d3.forceX(w / 2)) .force("y", d3.forceY(h / 2)) .force("collision", d3.forceCollide(r + 0.5).strength(1)); var nodes = [], centers = []; for (var i = 0; i < 5; ++i) { for (var j = 0; j < 50; ++j) { nodes.push({ x: w / 2 + offset(), y: h / 2 + offset(), color: colors(i), // <-A type: i // <-B }); } } force.nodes(nodes); function offset() { return Math.random() * 100; } function boundX(x) { return x > (w - r) ? (w - r): (x > r ? x : r); } function boundY(y){ return y > (h - r) ? (h - r) : (y > r ? y : r); } svg.selectAll("circle") .data(nodes).enter() .append("circle") .attr("class", "node") .attr("cx", function (d) {return d.x;}) .attr("cy", function (d) {return d.y;}) .attr("fill", function(d){return d.color;}) .attr("r", 1e-6) .transition() .attr("r", r); force.on("tick", function() { var k = 0.1; nodes.forEach(function(node) { var center = centers[node.type]; if(center){ node.x += (center[0] - node.x) * k; // <-C node.y += (center[1] - node.y) * k; // <-D } }); svg.selectAll("circle") .attr("cx", function (d) {return boundX(d.x);}) .attr("cy", function (d) {return boundY(d.y);}); }); d3.select("body") .on("touchstart", touch) .on("touchend", touch); function touch() { d3.event.preventDefault(); centers = d3.touches(svg.node()); var g = svg.selectAll("g.touch") .data(centers, function (d) { return d.identifier; }); g.enter() .append("g") .attr("class", "touch") .attr("transform", function (d) { return "translate(" + d[0] + "," + d[1] + ")"; }) .append("circle") .attr("class", "touch") .attr("fill", function(d){return colors(d.identifier);}) .transition() .attr("r", 50); g.exit().remove(); } <\/script> </body> </html></script> </body> </html>
https://d3js.org/d3.v4.min.js
https://d3js.org/d3.v4.min.js