|
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.6/d3.min.js"></script> |
|
<script src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script> |
|
<form>Speed factor <input id="speed" name="speed" type="number" value="1"></input></form> |
|
<div id="viz"></div> |
|
<script> |
|
var dim = 600; |
|
|
|
var lookup = [[0,1],[0,3],[2,1],[2,3]]; |
|
|
|
var colors = { |
|
bars: ["#800080","#D55555","#008000","#D5D555"], |
|
circles: ["#ff0000","#0000ff","#ffff00","#aaaaaa"] |
|
}; |
|
|
|
var svg = d3.select("#viz") |
|
.append("svg") |
|
.attr("height",.75*dim) |
|
.attr("width",dim) |
|
.append("g"); |
|
|
|
var little = svg.selectAll("g.little") |
|
.data([0,1,2,3]).enter() |
|
.append("g") |
|
.attr("class","little") |
|
.attr("transform",(d) => "translate("+(dim * (1+d%2)/3)+","+(dim/3)+")"); |
|
|
|
little |
|
.append("circle") |
|
.attr("fill",(d) => colors.circles[d]) |
|
.attr("r",5); |
|
|
|
little |
|
.append("text") |
|
.style("font-size",12) |
|
.text((d) => d); |
|
|
|
var big = svg.selectAll("circle.big") |
|
.data([0,1]).enter() |
|
.append("circle") |
|
.attr("stroke","black") |
|
.attr("fill-opacity",0) |
|
.attr("class","big") |
|
.attr("r",dim/6) |
|
.attr("transform",(d,i) => "translate("+(dim * (1+i%2)/3)+","+(dim/3)+")") |
|
.attr("cx",0) |
|
.attr("cy",0); |
|
|
|
var bar = svg.selectAll("g.bar") |
|
.data([0,1,2,3]).enter() |
|
.append("g") |
|
.attr("class","bar") |
|
.attr("transform","translate(0,"+.55*dim+")") |
|
|
|
bar |
|
.append("rect") |
|
.attr("height",20) |
|
.attr("fill","black") |
|
.attr("x",35) |
|
.attr("y",(d,i) => i*25); |
|
|
|
bar |
|
.append("text") |
|
.attr("y",(d,i) => i*25 + 15); |
|
|
|
var lines = svg.selectAll("path") |
|
.data([0,1,2,3]).enter() |
|
.append("path") |
|
.attr("class","line") |
|
.attr("stroke-width",3) |
|
.attr("transform",(d) => "translate("+(dim/3)+","+(dim/3)+")"); |
|
|
|
var t = d3.timer(function(elapsed){ |
|
|
|
speed = $('input#speed').val()/1000; |
|
|
|
little |
|
.selectAll("text") |
|
.attr("x",(d) => 5 + trigX(elapsed,d)) |
|
.attr("y",(d) => trigY(elapsed,d) - 5) |
|
|
|
little |
|
.selectAll("circle") |
|
.attr("cx",(d) => trigX(elapsed,d)) |
|
.attr("cy",(d) => trigY(elapsed,d)); |
|
|
|
bar.selectAll("rect") |
|
.attr("width",(d) => getD(lookup[d%4][0],lookup[d%4][1])) |
|
.attr("fill",(d) => colors.bars[d%4]); |
|
|
|
bar.selectAll("text") |
|
.text((d) => JSON.stringify(lookup[d%4])); |
|
|
|
lines |
|
.attr("stroke",(d) => colors.bars[d%4]) |
|
.attr("d",(d) => { |
|
return "M"+trigX(elapsed,lookup[d%4][0])+","+ |
|
trigY(elapsed,lookup[d%4][0])+ |
|
"L"+((dim/3)+trigX(elapsed,lookup[d%4][1]))+","+ |
|
trigY(elapsed,lookup[d%4][1]); |
|
}); |
|
|
|
}); |
|
|
|
function distance(a,b){ |
|
var d = Math.sqrt( |
|
((a.attr("cx")-b.attr("cx")-(dim/3))* |
|
(a.attr("cx")-b.attr("cx")-(dim/3))) + |
|
((a.attr("cy")-b.attr("cy"))* |
|
(a.attr("cy")-b.attr("cy"))) |
|
); |
|
return d; |
|
} |
|
|
|
function getD(a,b){ |
|
return distance(little.filter((d) => d==a).select("circle"), |
|
little.filter((d) => d==b).select("circle")); |
|
} |
|
|
|
function trigX(input,d){ |
|
// flip 2,3 |
|
var flip = (d >= 2 & d%2 === 1) | (d >= 2 & d%2 === 0) ? -1 : 1; |
|
var phase = (d%2 === 0) ? .5*Math.PI : 0; |
|
return flip*dim/6*Math.cos(speed*input - phase); |
|
} |
|
|
|
function trigY(input,d){ |
|
// flip 1,2 |
|
var flip = (d < 2 & d%2 === 1) | (d >= 2 & d%2 === 0) ? 1 : -1; |
|
var phase = (d%2 === 0) ? .5*Math.PI : 0; |
|
return flip*dim/6*Math.sin(speed*input - phase); |
|
} |
|
</script> |