xxxxxxxxxx
<html>
<head>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/d3@2.5.1/d3.js"></script>
<script type="text/javascript" src="boid.js"></script>
<script type="text/javascript" src="jwerty.js"></script>
<style type="text/css">
body {
background: #000;
}
ellipse {
fill: #fff;
}
path {
fill: none;
stroke: #fff;
stroke-opacity: .75;
stroke-linecap: round;
}
.mid {
stroke-width: 4px;
}
.tail {
stroke-width: 2px;
}
</style>
</head>
<body>
<script type="text/javascript">
var w = 960,
h = 500,
n = 100,
m = 10,
degrees = 180 / Math.PI,
mouse = [null, null];
function nullGravity() {
mouse[0] = mouse[1] = null;
}
d3.select(window).on("blur", nullGravity);
var pause = false;
jwerty.key('p', function () {
pause = !pause;
});
var spermatozoa = d3.range(n).map(function() {
var x = Math.random() * w, y = Math.random() * h;
var b = boid()
.position([Math.random() * w, Math.random() * h])
.velocity([Math.random() * 2 - 1, Math.random() * 2 - 1])
.gravityCenter(mouse)
.separationWeight(4)
.neighborRadius(50)
.desiredSeparation(40)
.mouseRadius(350)
.gravityMultiplier(30);
b.vx = Math.random() * 2 - 1,
b.vy = Math.random() * 2 - 1,
b.path = d3.range(m).map(function() { return [x, y]; }),
b.count = 0
return b;
});
// Compute initial positions.
var vertices = spermatozoa.map(function(boid) {
return boid(spermatozoa);
});
var svg = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h)
.on("mousemove", function() {
var m = d3.svg.mouse(this);
mouse[0] = m[0];
mouse[1] = m[1];
})
.on("mouseout", nullGravity);
var g = svg.selectAll("g")
.data(spermatozoa)
.enter().append("svg:g");
var head = g.append("svg:ellipse")
.attr("rx", 6.5)
.attr("ry", 4);
g.append("svg:path")
.map(function(d) { return d.path.slice(0, 3); })
.attr("class", "mid");
var tail = g.append("svg:g")
.attr("class", "tail")
tail
.append("svg:path")
.map(function(d) { return d.path; })
//.attr("class", "tail");
var tail_paths = g.selectAll("path");
d3.timer(function() {
if(pause) return false;
for (var i = -1; ++i < n;) {
var spermatozoon = spermatozoa[i],
path = spermatozoon.path,
//dx = spermatozoon.vx,
//dy = spermatozoon.vy;
dx = spermatozoon.velocity()[0],
dy = spermatozoon.velocity()[1];
vertices[i] = spermatozoon(spermatozoa);
path[0][0] = vertices[i][0];
path[0][1] = vertices[i][1];
var x = path[0][0] += dx,
y = path[0][1] += dy,
//x = vertices[i] += dx,
//y = vertices[i] += dy,
speed = Math.sqrt(dx * dx + dy * dy),
count = speed * 10,
k1 = -5 - speed / 3;
// Bounce off the walls.
//if (x < 0 || x > w) spermatozoon.vx *= -1;
//if (y < 0 || y > h) spermatozoon.vy *= -1;
angle = Math.atan2(spermatozoon.velocity()[0], spermatozoon.velocity()[1]) * degrees
// Swim!
for (var j = 0; ++j < m;) {
var vx = x - path[j][0],
vy = y - path[j][1],
k2 = Math.sin(((spermatozoon.count += count) + j * 3) / 300) / speed;
path[j][0] = (x += dx / speed * k1) - dy * k2;
path[j][1] = (y += dy / speed * k1) + dx * k2;
speed = Math.sqrt((dx = vx) * dx + (dy = vy) * dy);
}
///spermatozoon.vx = spermatozoon.velocity[0]
//spermatozoon.vy = spermatozoon.velocity[1]
}
head.attr("transform", function(d,i) {
//return "translate(" + d.path[0] + ")rotate(" + Math.atan2(d.vy, d.vx) * degrees + ")";
//return "translate(" + vertices[i] + ")rotate(" + Math.atan2(d.vy, d.vx) * degrees + ")";
var angle = 90-Math.atan2(d.velocity()[0], d.velocity()[1]) * degrees;// + 180;
return "translate(" + vertices[i] + ")rotate(" + angle + ")";
});
tail
/*
.attr("transform", function(d,i) {
//return "translate(" + [-vertices[i][0], -vertices[i][1]] + ")";
//d3.select(this.parentNode)
var angle = Math.atan2(d.velocity()[0], d.velocity()[1]) * degrees + 90;
return "rotate(" + angle + ", " + vertices[i] + ")";
})
*/
tail_paths
.attr("d", function(d) {
return "M" + d.join("L");
});
});
</script>
</body>
</html>
Modified http://mbostock.github.com/d3/d3.js?2.5.0 to a secure url
https://mbostock.github.com/d3/d3.js?2.5.0