Skip to content

Instantly share code, notes, and snippets.

@JerryLeeCS
Forked from veltman/README.md
Created June 10, 2020 05:12
Show Gist options
  • Save JerryLeeCS/c0b9bbe3f9ab282153efd16db3ea5686 to your computer and use it in GitHub Desktop.
Save JerryLeeCS/c0b9bbe3f9ab282153efd16db3ea5686 to your computer and use it in GitHub Desktop.
Particle tentacles

This got a little weird.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
</head>
<body>
<canvas width="960" height="500"></canvas>
<canvas width="960" height="500" class="offscreen" style="display: none;"></canvas>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var width = 960,
height = 500;
var canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
offscreen = document.querySelector(".offscreen"),
offscreenContext = offscreen.getContext("2d");
offscreenContext.globalAlpha = 0.8;
var numDots = 1200;
var points = d3.range(numDots).map(function(d, i){
return {
position: new Vec2(Math.random() * width, Math.random() * height),
velocity: new Vec2(Math.random() * 3, Math.random() * 3)
};
});
d3.shuffle(points);
points.forEach(function(p, i){
p.target = points[i + 1] || points[0];
p.color = d3.interpolateRainbow(i / numDots);
});
var maxVelocity = 3,
maxForce = 0.4;
d3.timer(function(t){
points.forEach(function(p){
var destination = p.target.position.clone(),
desiredVelocity = destination.subtract(p.position).normalize().scale(maxVelocity),
steering = desiredVelocity.subtract(p.velocity).truncate(maxForce);
p.velocity.add(steering).truncate(maxVelocity);
});
offscreenContext.clearRect(0, 0, width, height);
offscreenContext.drawImage(canvas, 0, 0, width, height);
context.clearRect(0, 0, width, height);
context.drawImage(offscreen, 0, 0, width, height);
points.forEach(function(p, i){
// Wall bounces
if (p.position.x + p.velocity.x < 0 || p.position.x + p.velocity.x >= width) {
p.velocity.x = -p.velocity.x;
}
if (p.position.y + p.velocity.y < 0 || p.position.y + p.velocity.y >= height) {
p.velocity.y = -p.velocity.y;
}
p.position.add(p.velocity);
context.beginPath();
context.fillStyle = p.color;
context.arc(p.position.x, p.position.y, 2, 0, 2 * Math.PI);
context.fill();
});
});
function Vec2(x, y) {
this.x = x || 0;
this.y = y || 0;
return this;
};
Vec2.prototype.add = function(v) {
this.x += v.x;
this.y += v.y;
return this;
};
Vec2.prototype.clone = function() {
return new Vec2(this.x, this.y);
};
Vec2.prototype.subtract = function(v) {
this.x -= v.x;
this.y -= v.y;
return this;
};
Vec2.prototype.scale = function(s) {
this.x = this.x * s;
this.y = this.y * s;
return this;
};
Vec2.prototype.normalize = function() {
var length = this.length();
this.x = this.x / length;
this.y = this.y / length;
return this;
};
Vec2.prototype.length = function() {
return Math.sqrt(this.x * this.x + this.y * this.y);
};
Vec2.prototype.truncate = function(max) {
var length = this.length();
if (length > max) {
this.x = this.x * max / length;
this.y = this.y * max / length;
}
return this;
};
Vec2.prototype.dot = function(v) {
return this.x * v.x + this.y * v.y;
};
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment