[76] | 1 | // Based on http://vis.stanford.edu/protovis/ex/clock.html |
---|
| 2 | // Based on http://blog.pixelbreaker.com/polarclock |
---|
| 3 | |
---|
| 4 | var w = 960, |
---|
| 5 | h = 700, |
---|
| 6 | r = Math.min(w, h) / 1.8, |
---|
| 7 | s = .09, |
---|
| 8 | fsec = d3.time.format("%S s"), |
---|
| 9 | fmin = d3.time.format("%M m"), |
---|
| 10 | fhou = d3.time.format("%H h"), |
---|
| 11 | fwee = d3.time.format("%a"), |
---|
| 12 | fdat = d3.time.format("%d d"), |
---|
| 13 | fmon = d3.time.format("%b"); |
---|
| 14 | |
---|
| 15 | var fill = d3.scale.linear() |
---|
| 16 | .range(["hsl(-180, 50%, 50%)", "hsl(180, 50%, 50%)"]) |
---|
| 17 | .interpolate(d3.interpolateHsl); |
---|
| 18 | |
---|
| 19 | var arc = d3.svg.arc() |
---|
| 20 | .startAngle(0) |
---|
| 21 | .endAngle(function(d) { return d.value * 2 * Math.PI; }) |
---|
| 22 | .innerRadius(function(d) { return d.index * r; }) |
---|
| 23 | .outerRadius(function(d) { return (d.index + s) * r; }); |
---|
| 24 | |
---|
| 25 | var vis = d3.select("#clock").append("svg:svg") |
---|
| 26 | .attr("width", w) |
---|
| 27 | .attr("height", h) |
---|
| 28 | .append("svg:g") |
---|
| 29 | .attr("transform", "translate(" + w / 2 + "," + h / 2 + ")"); |
---|
| 30 | |
---|
| 31 | var g = vis.selectAll("g") |
---|
| 32 | .data(fields) |
---|
| 33 | .enter().append("svg:g"); |
---|
| 34 | |
---|
| 35 | g.append("svg:path") |
---|
| 36 | .style("fill", function(d) { return fill(d.value); }) |
---|
| 37 | .attr("d", arc); |
---|
| 38 | |
---|
| 39 | g.append("svg:text") |
---|
| 40 | .attr("text-anchor", "middle") |
---|
| 41 | .attr("dy", "1em") |
---|
| 42 | .text(function(d) { return d.text; }); |
---|
| 43 | |
---|
| 44 | |
---|
| 45 | // Update arcs. |
---|
| 46 | d3.timer(function() { |
---|
| 47 | var g = vis.selectAll("g") |
---|
| 48 | .data(fields); |
---|
| 49 | |
---|
| 50 | g.select("path") |
---|
| 51 | .style("fill", function(d) { return fill(d.value); }) |
---|
| 52 | .attr("d", arc); |
---|
| 53 | |
---|
| 54 | g.select("text") |
---|
| 55 | .attr("dy", function(d) { return d.value < .5 ? "-.5em" : "1em"; }) |
---|
| 56 | .attr("transform", function(d) { |
---|
| 57 | return "rotate(" + 360 * d.value + ")" |
---|
| 58 | + "translate(0," + -(d.index + s / 2) * r + ")" |
---|
| 59 | + "rotate(" + (d.value < .5 ? -90 : 90) + ")" |
---|
| 60 | }) |
---|
| 61 | .text(function(d) { return d.text; }); |
---|
| 62 | }); |
---|
| 63 | |
---|
| 64 | // Generate the fields for the current date/time. |
---|
| 65 | function fields() { |
---|
| 66 | var d = new Date; |
---|
| 67 | |
---|
| 68 | function days() { |
---|
| 69 | return 32 - new Date(d.getYear(), d.getMonth(), 32).getDate(); |
---|
| 70 | } |
---|
| 71 | |
---|
| 72 | var second = (d.getSeconds() + d.getMilliseconds() / 1000) / 60, |
---|
| 73 | minute = (d.getMinutes() + second) / 60, |
---|
| 74 | hour = (d.getHours() + minute) / 24, |
---|
| 75 | weekday = (d.getDay() + hour) / 7, |
---|
| 76 | date = (d.getDate() - 1 + hour) / days(), |
---|
| 77 | month = (d.getMonth() + date) / 12; |
---|
| 78 | |
---|
| 79 | return [ |
---|
| 80 | {value: second, index: .7, text: fsec(d)}, |
---|
| 81 | {value: minute, index: .6, text: fmin(d)}, |
---|
| 82 | {value: hour, index: .5, text: fhou(d)}, |
---|
| 83 | {value: weekday, index: .3, text: fwee(d)}, |
---|
| 84 | {value: date, index: .2, text: fdat(d)}, |
---|
| 85 | {value: month, index: .1, text: fmon(d)}, |
---|
| 86 | ]; |
---|
| 87 | } |
---|