Connected particles on svg and canvas, same codebase thanks to d3-canvas-transition module. Original canvas block connected particles III
Last active
January 4, 2017 18:18
-
-
Save lsbardel/8dd4c548e19ae0f420f8f91c4d3ac1d7 to your computer and use it in GitHub Desktop.
Connected Particles on Svg and Canvas
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: bsd-3-clause |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<title>Connected particles</title> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script src="https://giottojs.org/d3-canvas-transition/0.3.3/d3-canvas-transition.js"></script> | |
<style> | |
#panel { | |
background-color: rgba(245,245,245,0.9); | |
padding: 5px; | |
position: absolute; | |
display: block; | |
} | |
</style> | |
</head> | |
<body> | |
<div id='panel'"> | |
<div id="paper"> | |
<label> | |
<input id='svg' name="type" type="radio" checked> | |
<span>svg</span> | |
</label> | |
<label> | |
<input id='canvas' name="type" type="radio"> | |
<span>canvas</span> | |
</label> | |
</div> | |
<div id="fps">FPS: <span>?</span></div> | |
</div> | |
<div id="example" style="max-width: 960px"></div> | |
<script> | |
(function () { | |
d3.select('#svg').on('click', function () {draw('svg');}); | |
d3.select('#canvas').on('click', function () {draw('canvas');}); | |
if (d3.resolution() > 1) { | |
d3.select('#paper').append('label').html( | |
"<input id='canvas-low' name='type' type='radio'><span>canvas low resolution</span>" | |
); | |
d3.select('#canvas-low').on('click', function () {draw('canvas', 1);}); | |
} | |
var example = d3.select("#example"), | |
fps = d3.select("#fps span"), | |
width = d3.getSize(example.style('width')), | |
height = Math.min(500, width), | |
radius = 2.5, | |
minDistance = 40, | |
maxDistance = 60, | |
minDistance2 = minDistance * minDistance, | |
maxDistance2 = maxDistance * maxDistance, | |
n = 200, | |
particles = new Array(n), | |
paper; | |
for (var i = 0; i < n; ++i) { | |
particles[i] = { | |
x: Math.random() * width, | |
y: Math.random() * height, | |
vx: 0, | |
vy: 0 | |
}; | |
} | |
draw('svg'); | |
var time0 = d3.now(), frames = 0, time1; | |
d3.timer(function () { | |
redraw(); | |
frames++; | |
time1 = d3.now(); | |
if (time1 - time0 > 1000) { | |
fps.text(Math.round(1000*frames/(time1 - time0))); | |
time0 = time1; | |
frames = 0; | |
} | |
}); | |
function draw (type, r) { | |
example.select('.paper').remove(); | |
paper = example | |
.append(type) | |
.classed('paper', true) | |
.attr('width', width).attr('height', height).canvasResolution(r).canvas(true) | |
.style('fill', '#666') | |
.style('stroke', '#666'); | |
paper.append('g').classed('circles', true) | |
.selectAll('circle') | |
.data(particles) | |
.enter() | |
.append('circle').attr('r', radius) | |
.style('stroke-width', 0); | |
} | |
function redraw () { | |
paper.select('.circles').selectAll('circle') | |
.attr('cx', function (p) { | |
p.x += p.vx; | |
if (p.x < -maxDistance) p.x += width + maxDistance * 2; | |
else if (p.x > width + maxDistance) p.x -= width + maxDistance * 2; | |
p.vx += 0.2 * (Math.random() - .5) - 0.01 * p.vx; | |
return p.x; | |
}) | |
.attr('cy', function (p) { | |
p.y += p.vy; | |
if (p.y < -maxDistance) p.y += height + maxDistance * 2; | |
else if (p.y > height + maxDistance) p.y -= height + maxDistance * 2; | |
p.vy += 0.2 * (Math.random() - .5) - 0.01 * p.vy; | |
return p.y; | |
}); | |
paper.select('.lines').remove(); | |
var lines = paper.append('g').classed('lines', true), | |
opacity; | |
for (var i = 0; i < n; ++i) { | |
for (var j = i + 1; j < n; ++j) { | |
var pi = particles[i], | |
pj = particles[j], | |
dx = pi.x - pj.x, | |
dy = pi.y - pj.y, | |
d2 = dx * dx + dy * dy; | |
if (d2 < maxDistance2) { | |
opacity = d2 > minDistance2 ? (maxDistance2 - d2) / (maxDistance2 - minDistance2) : 1; | |
lines.append('line') | |
.attr('x1', pi.x).attr('y1', pi.y).attr('x2', pj.x).attr('y2', pj.y) | |
.style('opacity', opacity); | |
} | |
} | |
} | |
} | |
}()); | |
</script> | |
</body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment