Skip to content

Instantly share code, notes, and snippets.

@EmilienDupont
Last active May 16, 2017 05:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EmilienDupont/56f9b40b3284f49d88ad4be0cb622f5d to your computer and use it in GitHub Desktop.
Save EmilienDupont/56f9b40b3284f49d88ad4be0cb622f5d to your computer and use it in GitHub Desktop.
Mind

Mind

Trying to draw the contrast between a stressed and relaxed mind in d3.

<!DOCTYPE html>
<meta charset='utf-8'>
<style>
body {
background: #222
}
</style>
<body>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script>
var width = 960,
height = 500,
then = 0, // intial time step
base_velocity = 0.001, // rotation speed
theta_time = 0; // angle as a function of time
// Set up colors
var colors = [],
num_colors = 7;
for (var i = 0; i < num_colors; i++) {
colors.push(d3.interpolateGnBu(i / num_colors))
}
var svg = d3.select('body')
.append('svg')
.attr('width', width)
.attr('height', height);
var center = {'x': width/2, 'y': height/2};
/* Helper functions */
function get_random_item(items) {
return items[Math.floor(Math.random() * items.length)];
}
function angles_to_x_y(radius, theta, phi) {
// Get x, y coordinates of ellipse
var point = ellipse_coords(radius, theta);
// Tilt ellipse
var tilted_point = rotate(point, phi)
// Shift ellipse to center
return translate(tilted_point, center);
}
function ellipse_coords(radius, theta) {
return {'x': radius.x * Math.cos(theta),
'y': radius.y * Math.sin(theta)};
}
function rotate(point, phi) {
return {'x': point.x * Math.cos(phi) - point.y * Math.sin(phi),
'y': point.x * Math.sin(phi) + point.y * Math.cos(phi)};
}
function translate(point, shift) {
return {'x': point.x + shift.x,
'y': point.y + shift.y};
}
function depth_proj(theta) {
return 1 + 0.5 * Math.sin(theta);
}
function get_particle() {
// could be interesting to make e.g. smaller particles faster and travelling
// at a larger radius
var tilt = Math.PI * (0.5 - Math.random());
traj_rx = 1 / (Math.abs(tilt) + 1) * width / 3. * Math.random();
traj_ry = tilt / Math.PI * height / 8. * Math.random();
var particle = {'size' : 3 * Math.random() + 3,
'theta_init' : 2 * Math.PI * Math.random(),
'phi' : tilt,
'traj_radius' : {'x': traj_rx, 'y': traj_ry},
'velocity' : 2 * Math.random() + 2,
'color' : get_random_item(colors)};
return particle
}
function get_particles(num_particles) {
var particles = [];
for (i = 0; i < num_particles; i++) {
particles.push(get_particle())
}
return particles;
}
/* Set up particles */
var particles_data = get_particles(400);
var particles = svg.selectAll('.particle')
.data(particles_data)
.enter()
.append('circle')
.style('mix-blend-mode', 'screen')
.attr('class', 'particle')
.attr('cx', function(d) { return angles_to_x_y(d.traj_radius, d.theta_init, d.phi).x; })
.attr('cy', function(d) { return angles_to_x_y(d.traj_radius, d.theta_init, d.phi).y; })
.attr('r', function(d) { return d.size * depth_proj(d.theta_init); })
.attr('fill', function(d) { return d.color; });
function redraw(theta) {
particles.attr('cx', function(d) { return angles_to_x_y(d.traj_radius, d.theta_init + d.velocity * theta, d.phi).x; })
.attr('cy', function(d) { return angles_to_x_y(d.traj_radius, d.theta_init + d.velocity * theta, d.phi).y; })
.attr('r', function(d) { return d.size * depth_proj(d.theta_init + d.velocity * theta); });
}
d3.timer(function(elapsed) {
// Periodically slow down and speed up rotation
if (elapsed % 15000 > 5000) {
base_velocity = 0.0001;
} else {
base_velocity = 0.001;
}
theta_time = theta_time + base_velocity * (elapsed - then);
redraw(theta_time);
then = elapsed;
})
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment