(function() { var D, END, HEIGHT, LIN_WIDTH, SAMPLES, START, STEP, WIDTH, a, b, data, drag, lin_end, lin_start, pinch_offset, redraw, spiral, svg, time; data = d3.range(0, 100, 1).concat([100]); data = data.map(function(t) { var d; d = { t: t }; if (t % 10 === 0) { d.highlight = true; } if (t === 42) { d.answer = true; } return d; }); WIDTH = 960; HEIGHT = 500; svg = d3.select('body').append('svg').attr({ width: WIDTH, height: HEIGHT }).append('g').attr({ transform: "translate(" + (WIDTH / 2) + ",160)" }); a = 0; D = 40; b = D / (2 * Math.PI); SAMPLES = 80; svg.append('line').attr({ "class": 'my_axis debug', x1: -WIDTH, x2: WIDTH }); svg.append('line').attr({ "class": 'my_axis debug', y1: -HEIGHT, y2: HEIGHT }); spiral = svg.append('path').attr({ "class": 'spiral' }); START = 0; END = 100; STEP = 0.1; time = d3.range(START, END + STEP, STEP).map(function(t) { return { t: t }; }); LIN_WIDTH = 500; lin_start = 30; lin_end = 44; spiral = svg.append('path').attr({ "class": 'spiral' }); redraw = function() { var delta, delta_theta_l, delta_theta_r, dots, line_generator, radius_l, radius_r, spiral_layout, t2l, t2lr, t2ltheta, t2rr, t2rtheta, theta_max_l, theta_max_r; t2l = d3.scale.linear().domain([lin_start, lin_end]).range([-LIN_WIDTH / 2, LIN_WIDTH / 2]); delta = t2l(1) - t2l(0); theta_max_l = Math.sqrt(delta * (lin_start - START) / b); radius_l = a + b * theta_max_l; delta_theta_l = delta / radius_l; t2ltheta = d3.scale.linear().domain([START, lin_start]).range([-Math.PI / 2 - theta_max_l, -Math.PI / 2]); t2lr = d3.scale.linear().domain([START, lin_start]).range([0, radius_l]); theta_max_r = Math.sqrt(delta * (END - lin_end) / b); radius_r = a + b * theta_max_r; delta_theta_r = delta / radius_r; t2rtheta = d3.scale.linear().domain([lin_end, END]).range([-Math.PI / 2, -Math.PI / 2 + theta_max_r]); t2rr = d3.scale.linear().domain([lin_end, END]).range([radius_r, 0]); spiral_layout = function(d) { if (d.t < lin_start) { d.theta = t2ltheta(d.t); d.r = t2lr(d.t); d.x = -LIN_WIDTH / 2 + d.r * Math.cos(d.theta); d.y = radius_l + d.r * Math.sin(d.theta); return d; } if (d.t <= lin_end) { d.x = t2l(d.t); d.y = 0; return d; } d.theta = t2rtheta(d.t); d.r = t2rr(d.t); d.x = +LIN_WIDTH / 2 + d.r * Math.cos(d.theta); d.y = radius_r + d.r * Math.sin(d.theta); return d; }; line_generator = d3.svg.line().x(function(d) { return d.x; }).y(function(d) { return d.y; }).interpolate('linear'); spiral.datum(time.map(spiral_layout)).attr({ d: line_generator }); dots = svg.selectAll('.dot').data(data.map(spiral_layout)); dots.enter().append('circle').attr({ "class": 'dot' }); dots.attr({ cx: function(d) { return d.x; }, cy: function(d) { return d.y; }, r: function(d) { if (d.highlight || d.answer) { return 4; } else { return 2; } }, fill: function(d) { if (d.answer) { return 'rgb(231, 41, 138)'; } else { return 'rgb(27, 158, 119)'; } } }); svg.append('circle').attr({ "class": 'radius_indicator debug', cx: -LIN_WIDTH / 2, cy: radius_l, r: radius_l }); return svg.append('circle').attr({ "class": 'radius_indicator debug', cx: LIN_WIDTH / 2, cy: radius_r, r: radius_r }); }; redraw(); pinch_offset = null; drag = d3.behavior.drag().on('drag', function() { var delta, offset, t2l; t2l = d3.scale.linear().domain([lin_start, lin_end]).range([-LIN_WIDTH / 2, LIN_WIDTH / 2]); delta = t2l(1) - t2l(0); if (pinch_offset == null) { pinch_offset = d3.event.x; } offset = (d3.event.x - pinch_offset) / delta; if (lin_start - offset >= START && lin_end - offset <= END) { lin_start -= offset; lin_end -= offset; } pinch_offset = d3.event.x; return redraw(); }).on('dragend', function() { return pinch_offset = null; }); svg.append('rect').attr({ "class": 'overlay', width: WIDTH, height: D * 3, x: -WIDTH / 2, y: -D * 3 / 2 }).call(drag); }).call(this);