|
var width = 400, |
|
height = 430, |
|
num_axes = 12, |
|
tick_axis = 9, |
|
start = 0, |
|
firstJan = 0.25, |
|
end = 2.25, |
|
startDate = new Date(2015,10,1); |
|
|
|
var theta = function(r) { |
|
return 2*Math.PI*r; |
|
}; |
|
|
|
|
|
var months = ['Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec','Jan','Feb','Mar']; |
|
|
|
|
|
var r = d3.min([width,height])/2-40; |
|
var r2 = r; |
|
|
|
var radius = d3.scale.linear() |
|
.domain([start, end]) |
|
.range([0, r]); |
|
|
|
var angle = d3.scale.linear() |
|
.domain([0,num_axes]) |
|
.range([0,360]) |
|
|
|
|
|
|
|
var svg = d3.select("#chart").append("svg") |
|
.attr("width", width) |
|
.attr("height", height) |
|
.append("g") |
|
.attr("transform", "translate(" + width/2 + "," + (height/2+8) +")"); |
|
|
|
var pieces = d3.range(start, end+0.001, (end-start)/1000); |
|
|
|
var spiral = d3.svg.line.radial() |
|
.interpolate("cardinal") |
|
.angle(theta) |
|
.radius(radius); |
|
|
|
|
|
|
|
|
|
|
|
svg.selectAll("circle.tick") |
|
.data(d3.range(firstJan,(end+0.001),1)) |
|
.enter().append("circle") |
|
.attr("class", "tick") |
|
.attr("cx", 0) |
|
.attr("cy", 0) |
|
.attr("r", function(d) { return radius(d); }); |
|
|
|
svg.selectAll(".axis") |
|
.data(d3.range(num_axes)) |
|
.enter().append("g") |
|
.attr("class", "axis") |
|
.attr("transform", function(d) { return "rotate(" + -angle(d) + ")"; }) |
|
.call(radial_tick); |
|
|
|
|
|
svg.selectAll("text.year") |
|
.data(['2016','2017']) |
|
.enter() |
|
.append("text") |
|
.attr("x","0") |
|
.attr("y",function(d,i){ return (i*-80)-35; }) |
|
.attr("class","year") |
|
.attr("text-anchor","middle") |
|
.text(function(d){ return d; }); |
|
|
|
|
|
|
|
svg.selectAll("text.months") |
|
.data(d3.range(num_axes)) |
|
.enter().append("text") |
|
.attr("class","months") |
|
.attr("y", radius(end)+13) |
|
.text(function(d,i) { return months[i]; }) |
|
.attr("text-anchor", "middle") |
|
.attr("transform", function(d,i) { |
|
var tempX = Math.round(1.15*(r * Math.cos((angle(d)/180)*Math.PI))); |
|
var tempY = Math.round(1.1*(r * Math.sin((angle(d)/180)*Math.PI))) - r - 6; |
|
return "translate(" + tempX + ", " + tempY + ")"; |
|
}); |
|
|
|
|
|
svg.selectAll(".spiral") |
|
.data([pieces]) |
|
.enter().append("path") |
|
.attr("class", "spiral") |
|
.attr("d", spiral) |
|
.attr("transform", function(d) { return "rotate(" + (-90) + ")" });//starts in October |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var periods = []; |
|
periods[0] = {startDay:6, startMth:4, startYear:2016, endDay:31, endMth:1, endYear:2017}; |
|
periods[1] = {startDay:1, startMth:6, startYear:2016, endDay:1, endMth:3, endYear:2017}; |
|
periods[2] = {startDay:1, startMth:6, startYear:2016, endDay:1, endMth:6, endYear:2017}; |
|
periods[3] = {startDay:8, startMth:10, startYear:2016, endDay:5, endMth:11, endYear:2016}; |
|
|
|
var specialDays = []; |
|
specialDays[0] = { day: 1, month: 6, year: 2016, ref:2 }; |
|
specialDays[1] = { day: 2, month: 3, year: 2017, ref:2 }; |
|
specialDays[2] = { day: 1, month: 6, year: 2017, ref:2}; |
|
specialDays[3] = { day: 1, month: 6, year: 2016, ref:1}; |
|
specialDays[4] = { day: 1, month: 3, year: 2017, ref:1}; |
|
specialDays[5] = { day: 6, month: 4, year: 2016, ref:0}; |
|
specialDays[6] = { day: 31, month: 1, year: 2017, ref:0}; |
|
specialDays[7] = { day: 8, month: 10, year: 2016, ref:3}; |
|
specialDays[8] = { day: 5, month: 11, year: 2016, ref:3}; |
|
|
|
|
|
for (var p=0; p<periods.length; p++) { |
|
|
|
|
|
var date1 = new Date(periods[p].startYear, periods[p].startMth, periods[p].startDay); |
|
var date2 = new Date(periods[p].endYear, periods[p].endMth, periods[p].endDay); |
|
|
|
|
|
|
|
var timeDiff1 = Math.abs(date1.getTime() - startDate.getTime()); |
|
var diffDays1 = (Math.ceil(timeDiff1 / (1000 * 3600 * 24)))/365; |
|
|
|
var timeDiff2 = Math.abs(date2.getTime() - startDate.getTime()); |
|
var diffDays2 = (Math.ceil(timeDiff2 / (1000 * 3600 * 24)))/365; |
|
|
|
var pieces2 = d3.range(diffDays1, diffDays2+0.001, (diffDays2 - diffDays1)/1000); |
|
|
|
(p==0) ? r2 = r * 1.025 : r2 = r * 1.06 ; |
|
|
|
r = r2; |
|
|
|
var theta2 = function(r2) { |
|
return 2*Math.PI*r2; |
|
}; |
|
|
|
var radius2 = d3.scale.linear() |
|
.domain([start, end]) |
|
.range([0, r2]); |
|
|
|
var spiral2 = d3.svg.line.radial() |
|
.interpolate("cardinal") |
|
.angle(theta2) |
|
.radius(radius2); |
|
|
|
svg.selectAll(".spiral"+p) |
|
.data([pieces2]) |
|
.enter().append("path") |
|
.attr("class", "spiral"+p) |
|
.attr("d", spiral2) |
|
.attr("transform", function(d) { return "rotate(" + (-90) + ")" });//starts in October |
|
|
|
|
|
for (var q=0; q<specialDays.length; q++) {//specialDays.length |
|
|
|
if (specialDays[q].ref==p) { |
|
|
|
var date1 = new Date(specialDays[q].year, specialDays[q].month, specialDays[q].day); |
|
|
|
var timeDiff1 = Math.abs(date1.getTime() - startDate.getTime()); |
|
var diffDays1 = (Math.ceil(timeDiff1 / (1000 * 3600 * 24)))/365; |
|
|
|
var rad = radius2(diffDays1); |
|
var ang = angle(specialDays[q].month + ((specialDays[q].day-1)/30))-30-90; |
|
|
|
|
|
var x = rad * Math.cos((ang/180)*Math.PI); |
|
var y = rad * Math.sin((ang/180)*Math.PI); |
|
|
|
svg.append("circle").attr("cx",x).attr("cy",y).attr("r","3").attr("class","dot dot"+p); |
|
|
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
function radial_tick(selection) { |
|
selection.each(function(axis_num) { |
|
d3.svg.axis() |
|
.scale(radius) |
|
.ticks(3) |
|
.tickValues( axis_num == tick_axis ? [] : []) |
|
.orient("top")(d3.select(this)) |
|
|
|
}); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|