D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
KristinHenry
Full window
Github gist
particles
<!doctype html> <meta charset="utf-8"> <head> <title>Testing interactive svg + canvas plot</title> <style> body { margin: 0; } svg { position: absolute; top: 0; left: 0; } rect { fill: transparent; } </style> <script src='https://d3js.org/d3.v3.min.js'></script> </head> <body style="background-color: #246980"> <script type='text/javascript'> var filler = '#eee'; var prp1 = '#7b3294'; var prp2 = '#c2a5cf'; var grn1 = '#a6dba0'; var grn2 = '#008837'; var colors = [filler, prp1, prp2, grn1, grn2]; function randomRange(min, max){ return Math.floor((Math.random() * (max - min + 1)) + min); } function getDir(){ if(randomRange(0,1) == 1){ return 1;} return -1; } var map = {}; map.width = 1050; map.height = 1500; var xmin = 20; var xmax = map.width-20; var ymin = 20; var ymax = map.height-20; var s = 1; var maxNodesCan = map.width/2; //200; var maxNodesSVG = maxNodesCan/10; //20; map.canvas = d3.select('body') .append('canvas') .attr('width', map.width) .attr('height', map.height) .node().getContext('2d'); map.svg = d3.select('body') .append('svg') .attr('width', map.width) .attr('height', map.height) .append('g'); map.svg.append('rect') .attr('class', 'overlay') .attr('width', map.width) .attr('height', map.height); /* Initialize particles */ // background molecules var rmin = 10; map.canvas.nodes = d3.range(maxNodesCan).map(function(d, i) { return { x: randomRange(xmin,xmax), y: randomRange(ymin,ymax), r: randomRange(3,20) + rmin, t: 0, dx: getDir(), dy: getDir() }; }); // interactive molecules map.svg.nodes = d3.range(maxNodesSVG).map(function(d, i) { var t = randomRange(1,colors.length-1); return { x: randomRange(xmin,xmax), y: randomRange(ymin,ymax), r: t*5 + 2 + rmin, t: t, dx: getDir(), dy: getDir() }; }); map.nodes = map.svg.nodes.concat( map.canvas.nodes ); var root = map.nodes[0]; root.r = 0; root.fixed = true; map.canvas.draw = function() { map.canvas.clearRect(0, 0, map.width, map.height); map.canvas.beginPath(); var i = -1, cx, cy; while (++i < map.canvas.nodes.length) { d = map.canvas.nodes[i]; map.canvas.fillStyle = colors[d.t]; cx = d.x; cy = d.y; map.canvas.moveTo(cx, cy); map.canvas.arc(cx, cy, d.r, 0, 2 * Math.PI); } map.canvas.fill(); }; map.svg.draw = function() { circle = map.svg.selectAll('circle') .data(map.svg.nodes).enter() .append('circle') .attr('r', function(d) { return d.r; }) .attr('fill', function(d){return colors[d.t];}) .attr('transform', map.svg.transform); }; // initial draw of molecules map.canvas.draw(); map.svg.draw(); map.redraw = function() { map.canvas.draw(); circle.attr('transform', map.svg.transform); }; map.svg.transform = function(d) { return 'translate(' + d.x + ',' + d.y + ')'; }; map.redraw(); map.updatePositions = function(){ var d; var q = d3.geom.quadtree(map.nodes) for(var i=0; i<map.canvas.nodes.length; i++){ d = map.canvas.nodes[i]; q.visit(collide(d)); testBounds(d); } for(var i=0; i<map.svg.nodes.length; i++){ d = map.svg.nodes[i]; q.visit(collide(d)); testBounds(d); } } var timer_ret_val = false; // Keeps a record of the elapsed time since the timer began. var timer_elapsed = 0; // Kick off the timer, and the action begins: d3.timer(tickFxn); function tickFxn(_elapsed) { timer_elapsed = _elapsed; map.updatePositions(); map.redraw(); var q = d3.geom.quadtree(map.nodes); return timer_ret_val; } //--------------------------------------------------- function testBounds(mol){ if(mol.x <= (xmin+mol.r) ){ mol.dx = s; } else if(mol.x >= (xmax-mol.r) ){ mol.dx = -s; } if(mol.y < (ymin+2*mol.r)){ mol.dy = s; } else if(mol.y >= (ymax-2*mol.r)){ mol.dy = -s; } mol.x += mol.dx; mol.y += mol.dy; } function collide(node) { var b = .8; var r = node.r + 1, nx1 = node.x - r, nx2 = node.x + r, ny1 = node.y - r, ny2 = node.y + r; //then check nearby particles in quadtree return function(quad, x1, y1, x2, y2) { if (quad.point && (quad.point !== node)) { var x = node.x - quad.point.x, y = node.y - quad.point.y, l = Math.sqrt(x * x + y * y), r = node.r + quad.point.r + 3; if (l < r) { l = (l - r) / l * b; node.x -= x *= l; node.y -= y *= l; quad.point.x += x; quad.point.y += y; } } return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1; }; } </script> </body>
Modified
http://d3js.org/d3.v3.min.js
to a secure url
https://d3js.org/d3.v3.min.js