|
|
|
function form_outline_d(form_n, x, y){ |
|
|
|
// square |
|
if (form_n == 0) { |
|
return "M" + (x) + "," + (y) + "l10,0 l0,10 l-10,0 z" |
|
} |
|
|
|
// triangle |
|
if (form_n == 1) { |
|
return "M" + (x) + "," + (y + 10) + "l5,-10 l5,10 z" |
|
} |
|
|
|
// circle |
|
if (form_n == 2) { |
|
return "M" + (x) + "," + (y + 5) + "a 5 5 0 1 0 0.01 0 z" |
|
} |
|
|
|
} |
|
|
|
|
|
function start_inventory_animation() { |
|
|
|
// vis config variables |
|
|
|
var svg = d3.select("#inventory-cycle") |
|
|
|
var speed = 0.00015 // ticks per millisecond |
|
|
|
var outer_r = 210 |
|
var inner_r = 160 |
|
|
|
var center_x = 289 |
|
var center_y_main = 380 |
|
var center_y_in = -30 |
|
|
|
// mapping functions |
|
|
|
var coord_x_in = function(r,a) { return center_x + r * Math.cos(a) } |
|
var coord_y_in = function(r,a) { return center_y_in+ r * Math.sin(a) } |
|
|
|
var coord_x_main = function(r,a) { return center_x + r * Math.cos(a) } |
|
var coord_y_main = function(r,a) { return center_y_main + r * Math.sin(a) } |
|
|
|
var angle_in = function(t, t1, t2) { |
|
var rel_t |
|
if (t2 == t1) { rel_t = 1 } |
|
else { rel_t = (t - t1) / (t2 - t1) } |
|
var a = (180.0 - 90.0 * rel_t) * (Math.PI/180.0) |
|
return a |
|
} |
|
|
|
var angle_main = function(t, t1, t2, e1, e2) { |
|
// compute angle in circle for a dot, |
|
// given its previous and next events, their timestamps, and the current time |
|
var rel_t |
|
if (t2 == t1) { rel_t = 1 } |
|
else { rel_t = (t - t1) / (t2 - t1) } |
|
|
|
if (e2 == 1) { |
|
return (90.0 + 180.0 * rel_t) * (Math.PI/180.0) |
|
} |
|
|
|
if (e2 == 2) { |
|
return (-90.0 + 135.0 * rel_t) * (Math.PI/180.0) |
|
} |
|
|
|
if (e2 == 3) { |
|
return (-90.0 + 135.0 + 45.0 * rel_t) * (Math.PI/180.0) |
|
} |
|
|
|
} |
|
|
|
// internal state variables |
|
var particle_count = 0 |
|
var current_events = [] |
|
|
|
d3.timer(function(t_ms) { |
|
var t = t_ms * speed |
|
|
|
// *** SIMULATION *** |
|
|
|
// check for expired events since last t |
|
// if previous event was #1, then move to #2 with random speed |
|
// if previous event was #2, then move to either #3 or #4 with some probability and random speed |
|
// if previous event was #3, then move to either #4 or #1 with some probability and random speed |
|
// if previous event was #4, then exit |
|
var removals = [] |
|
current_events.forEach(function(d,i){ |
|
if (d.t2 < t) { |
|
d.t1 = d.t2 |
|
d.e1 = d.e2 |
|
d.t2 = d.t1 + 0.3 + Math.random() * 0.4 |
|
if (d.e1 == 1) { |
|
d.e2 = 2 |
|
} else if (d.e1 == 2) { |
|
if (Math.random() < 0.5) { d.e2 = 4; d.t2 = d.t1 + 0.5 * ( 0.3 + Math.random() * 0.4 ) } |
|
else { d.e2 = 3 } |
|
} else if (d.e1 == 3) { |
|
if (Math.random() < 0.5) { d.e2 = 4; d.t2 = d.t1 + 0.5 * ( 0.3 + Math.random() * 0.4 ) } |
|
else { d.e2 = 1 } |
|
} else { |
|
removals.push(i) |
|
} |
|
} |
|
}) |
|
|
|
for (var i=removals.length - 1; i>-1; i--){ |
|
current_events.splice(removals[i],1) |
|
} |
|
|
|
// add some new particles, with some probability and random speed |
|
for (var i=0; i<2; i++) { |
|
if (Math.random() < 0.3) { |
|
particle_count += 1 |
|
current_events.push({ |
|
'particle_id': particle_count, |
|
'rad': inner_r + (outer_r - inner_r) * Math.random(), |
|
'sil': Math.floor(Math.random() * 3), |
|
't1': t, |
|
't2': t + 0.5 * ( 0.3 + Math.random() * 0.4 ), |
|
'e1': 0, |
|
'e2': 1 |
|
}) |
|
} |
|
} |
|
|
|
// *** UPDATE SVG ANIMATION *** |
|
|
|
var inventory_items = svg.selectAll(".inventory-cycle-silhouette") |
|
.data(current_events, function(d) { return d.particle_id }) |
|
|
|
inventory_items.enter().append("path") |
|
.attr("class", "inventory-cycle-silhouette") |
|
.attr("fill", "#fff") |
|
.attr("stroke", "#000") |
|
.attr("stroke-width", 0.5) |
|
.attr("opacity", 1) |
|
.attr("d", function(d) { return form_outline_d(d.sil, 290, 0) }) |
|
|
|
inventory_items |
|
.attr("d", function(d){ |
|
|
|
var tx, ty |
|
|
|
if (d.e1 == 0) { |
|
var new_rad = inner_r + (outer_r - d.rad) |
|
if (coord_y_in(new_rad, angle_in(t, d.t1, d.t2, d.e1, d.e2)) > center_y_main - outer_r + new_rad) { |
|
tx = coord_x_in(new_rad, angle_in(t, d.t1, d.t2, d.e1, d.e2)) |
|
} else { |
|
tx = -90 + d.rad * 2 |
|
} |
|
ty = coord_y_in(new_rad, angle_in(t, d.t1, d.t2, d.e1, d.e2)) |
|
} else if (d.e2 == 4) { |
|
tx = 280 |
|
ty = 550 |
|
} else { |
|
tx = coord_x_main(d.rad, angle_main(t, d.t1, d.t2, d.e1, d.e2)) |
|
ty = coord_y_main(d.rad, angle_main(t, d.t1, d.t2, d.e1, d.e2)) |
|
} |
|
|
|
return form_outline_d(d.sil, tx, ty) |
|
|
|
}) |
|
|
|
inventory_items.exit().remove() |
|
|
|
|
|
}) |
|
|
|
} |
|
|