| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <style> | |
| body { | |
| background: #eee; | |
| font: 10px Helvetica; | |
| margin: auto; | |
| position: relative; | |
| width: 960px; | |
| } | |
| text { | |
| text-anchor: middle; | |
| alignment-baseline: middle; | |
| fill: #444; | |
| } | |
| .hour text { | |
| fill: #222; | |
| font-size: 16px; | |
| } | |
| .hour line { | |
| stroke: #222; | |
| } | |
| .hour.hand { | |
| line-width: 3px; | |
| } | |
| .minute text { | |
| display: none; | |
| fill: #444; | |
| font-size: 8px; | |
| } | |
| .minute line { | |
| stroke: #444; | |
| } | |
| </style> | |
| <body> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> | |
| <script> | |
| var width = 960, | |
| height = 500, | |
| radius = 94; | |
| var svg = d3.select("body").append("svg") | |
| .attr("width", width) | |
| .attr("height", height) | |
| .append("g") | |
| .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); | |
| var field = svg.selectAll("g") | |
| .data(fields) | |
| .enter().append("g") | |
| .attr("class", "field"); | |
| field.append("line") | |
| .attr("class", function(d) { return d.field + " hand"; }) | |
| .attr("stroke-width", function(d) { return d.strokeWidth; }) | |
| .attr("stroke-linecap", "round") | |
| .attr("x1", 0) | |
| .attr("x2", function(d) { return d.length; }) | |
| .attr("y1", 0) | |
| .attr("y2", 0); | |
| svg.append("circle") | |
| .attr("cx", 0) | |
| .attr("cy", 0) | |
| .attr("r", 3) | |
| .attr("fill", "#c22"); | |
| // minute hands | |
| var minutedomain = d3.range(60); | |
| var minuteangle = d3.scale.linear() | |
| .domain([0,60]) | |
| .range([180,-180]) | |
| var minutemarks = svg.selectAll(".minute.axis") | |
| .data(minutedomain) | |
| .enter().append("g") | |
| .attr("class", "minute") | |
| .attr("transform", function(d) { return "rotate(" + -minuteangle(d) + ")"; }) | |
| minutemarks | |
| .filter(function(d) { return d % 5 == 0; }) | |
| .append("text") | |
| .attr("y", 190) | |
| .attr("transform", function(d) { | |
| return "rotate(" + minuteangle(d) + ",0,190)"; | |
| }) | |
| .text(String); | |
| minutemarks | |
| .append("line") | |
| .attr("x1", 168) | |
| .attr("x2", 180) | |
| .attr("y1", 0) | |
| .attr("y2", 0); | |
| // hour hands | |
| var hourdomain = d3.range(12); | |
| var hourangle = d3.scale.linear() | |
| .domain([0,12]) | |
| .range([180,-180]) | |
| var hourmarks = svg.selectAll(".hour.axis") | |
| .data(hourdomain) | |
| .enter().append("g") | |
| .attr("class", "hour") | |
| .attr("transform", function(d) { return "rotate(" + -hourangle(d) + ")"; }) | |
| hourmarks | |
| .append("text") | |
| .attr("y", 200) | |
| .attr("transform", function(d) { | |
| return "rotate(" + hourangle(d) + ",0,200)"; | |
| }) | |
| .text(String); | |
| hourmarks | |
| .append("line") | |
| .attr("stroke-width", 2) | |
| .attr("x1", 156) | |
| .attr("x2", 180) | |
| .attr("y1", 0) | |
| .attr("y2", 0); | |
| var counter = 0; | |
| function tick() { | |
| if (counter++ % 3 != 0) return; // ease up on cpu | |
| field.data(fields) | |
| .select("line") | |
| .attr("transform", function(d) { return "rotate(" + (360*d.value-90)+ ")" }) | |
| .style("stroke", function(d) { return d.color; }); | |
| } | |
| d3.timer(tick); | |
| function fields() { | |
| var now = new Date; | |
| var milliseconds = now.getMilliseconds(); | |
| var seconds = now.getSeconds() + milliseconds / 1000; | |
| var minutes = now.getMinutes() + seconds / 60; | |
| var hours = ((now.getHours() + 24) % 12 || 0) + minutes / 60; | |
| return [ | |
| {field: "hours", color: "#222", length: 102, strokeWidth: 6, index: .555, spacing: 0.1, value: hours / 12}, | |
| {field: "minutes", color: "#222", length: 154, strokeWidth: 3, index: .597, spacing: 0.115, value: minutes / 60}, | |
| {field: "seconds", color: "#c22", length: 180, strokeWidth: 1.5, index: .6348, spacing: 0.015, value: seconds / 60} | |
| ]; | |
| } | |
| </script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment