var w = 960, h = 500, scale = 1; var r2d = function(radians) { return radians * 180 / π} var d2r = function(degrees) { return degrees / 180 * π} var sin = function(radians) { return Math.sin(radians)} var cos = function(radians) { return Math.cos(radians)} var tan = function(radians) { return Math.tan(radians)} var svg = d3.select("body").append("svg") .attr("width", w) .attr("height", h) var background = svg.append("rect").attr("id", "background") .attr({"width":w, "height":h}) var g0 = svg.append("g").attr ("id", "g0") .attr ("transform", "translate(80 380) scale(" + scale + ")") // Append the centres of the two levers var master_centre = d3.select("#g0").append ("circle").attr("id", "master_centre") .attr ("cx","0") .attr ("cy","0").attr ("r","3") var point_circle = d3.select("#g0").append ("circle") .attr("id", "master_arc") .attr ("cx","0") .attr ("cy","0").attr ("r","500") var baseline = d3.select("#g0").append ("path") .attr("id", "base_line") .attr ("d","m 0 0 h 800") var master_report = g0.append("text").attr("id", "master_report") .attr("x", "-20") .attr("y", "-40") .text("0.00°") var slave_report = g0.append("text") .attr("id", "slave_report") .attr("x", "780") .attr("y", "-40") .text("0.00°") var slave_centre = g0.append ("circle") .attr("id", "slave_centre") .attr ("cx","800") .attr ("cy","0") .attr ("r","3") // The slave lever var slave_group = g0.append("g").attr("id", "slave_group") .attr("transform","translate(800 0)"); var slave = slave_group.append("path").attr ("id", "slave") .attr ("d","M 0 0 h-500") .attr("transform", "rotate(0)"); // The master lever var master_group = g0.append("g").attr("id", "master_group"); var master = master_group.append("path").attr ("id","master") .attr ("d","M 0 0 h500") .attr("transform", "rotate(0)") // See transition below var contact_height = master_group.append ("path").attr("id", "contact_height") .attr("d", "M 0 0 v -200") var i, n = 0, master_limit = -180 / Math.PI * Math.acos(400 / 500); var master_angles = [0.00002]; while ( n > master_limit) { master_angles.push(n); n -= 0.03; } // Calculate the side opposite to the master angle var rise = [], hshift = [], slave_angles = []; master_angles.shift(); // fudge for (var i = 0; i < master_angles.length; i++) { var a1 = sin(master_angles[i] / 180 * Math.PI); var a2 = cos(master_angles[i] / 180 * Math.PI); hshift.push (500 * cos(master_angles[i] / 180 * Math.PI)); var v = 500 * a1; rise.push (v); var h = (800 - (500 * a2)); slave_angles.push (Math.atan(h / -v) * 180 / Math.PI); } var run = function() { var tim; var text_entered = document.getElementById('ms').value * 1000; text_entered ? tim = text_entered : tim = 3000; master.transition() .delay(0) .ease ("linear") .duration(tim) .attrTween("transform", function() { return function(t) { var master_angle = master_angles[d3.round(t * master_angles.length - 1)]; d3.select("#master_report") .text((master_angle * -1).toFixed(2) + "°") var v = sin(master_angle / 180 * Math.PI) * 500; var h = 500 - cos(master_angle / 180 * Math.PI) * 500; return "rotate("+ master_angle +")"; }; } ) .transition() .delay(tim + 100) .duration(1000) .ease("bounce") .attr("transform", "rotate(0)") slave.transition() .delay(0) .ease ("linear") .duration(tim) .attrTween("transform", function() { return function(t) { var slave_angle = slave_angles[d3.round(t * slave_angles.length - 1)]; d3.select("#slave_report") .text((90 - slave_angle).toFixed(2) + "°") var slave_angle = slave_angles[d3.round(t * slave_angles.length - 1)]; return "rotate("+ (90-slave_angle) +")"; }; } ) .transition() .delay(tim) .duration(1000) .ease("bounce") .attr("transform", "rotate(0)") contact_height.transition() .delay(0) .ease ("linear") .duration(tim) .attrTween("d", function() { // was function(d, i) return function(t) { var height = rise[d3.round(t * (rise.length - 1))]; var x = hshift[d3.round(t * (hshift.length - 1))]; return "M "+ x +" 0 v 0 " + height; }; } ); } background .on("click", function() {run()}) run();