D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
lbrucel
Full window
Github gist
concentric clock d3.js
Built with
blockbuilder.org
<!DOCTYPE html> <head> <meta charset="utf-8"> <script src="https://d3js.org/d3.v4.min.js"></script> <style> body { margin: 0; position: fixed; top: 0; right: 0; bottom: 0; left: 0; background-color: #008080; } </style> </head> <body> <script> let margin = { top: 0, right: 0, bottom: 0, left: 0 } let width = window.innerWidth - margin.left - margin.right let height = window.innerHeight - margin.top - margin.bottom //-------------------------------------------------- // CLOCK CIRCLES //-------------------------------------------------- xyFromBase = (baseTime, radius, base) => { //baseTime is current minutes, seconds or hours //radius is distance from the current circle to the next outter circle //base is 60 for minutes and seconds; 12 for hours let radians = (baseTime * 360) / base radians = (radians * Math.PI) / 180 radians = radians - Math.PI / 2 return [Math.cos(radians) * radius, Math.sin(radians) * radius] } let svg = d3 .select('body') .append('svg') .attr('width', width) .attr('height', height) // faceRadius is 95% of smaller(width, height) let outterRadius = (Math.min(width, height) / 2) * 0.95 const hourLineWidth = 1, minuteLineWidth = 1, secondLineWidth = 1 const faceR = outterRadius const hourR = faceR * 0.75 const minR = hourR * 0.75 const secR = minR * 0.75 const hRadius = faceR - hourR const mRadius = hourR - minR const sRadius = minR - secR const date = new Date() let hours = date.getHours() % 12 let minutes = date.getMinutes() let seconds = date.getSeconds() //clock face is the maximum circle in the viewport, centered let faceCenter = [width / 2, height / 2] let clockFaceCircle = svg .append('circle') .style('fill', '#001be5') .attr('cx', faceCenter[0]) .attr('cy', faceCenter[1]) .attr('r', faceR) //hour circle hCenter = xyFromBase(hours, hRadius, 12) hCenter[0] += faceCenter[0] hCenter[1] += faceCenter[1] let hourCircle = svg .append('circle') .style('fill', '#990000') .style('stroke', '#990000') .style('stroke-width', hourLineWidth) .attr('cx', hCenter[0]) .attr('cy', hCenter[1]) .attr('r', hourR) //minute circle let mCenter = xyFromBase(minutes, mRadius, 60) mCenter[0] += hCenter[0] mCenter[1] += hCenter[1] let minuteCircle = svg .append('circle') .style('fill', '#20b2aa') .style('stroke', '#20b2aa') .style('stroke-width', minuteLineWidth) .attr('cx', mCenter[0]) .attr('cy', mCenter[1]) .attr('r', minR) //seconds circle sCenter = xyFromBase(seconds, sRadius, 60) sCenter[0] += mCenter[0] sCenter[1] += mCenter[1] let secondCircle = svg .append('circle') .style('fill', '#660066') .style('stroke', '#660066') .style('stroke-width', secondLineWidth) .attr('cx', sCenter[0]) .attr('cy', sCenter[1]) .attr('r', secR) updateClock = () => { let now = new Date() hours = now.getHours() % 12 minutes = now.getMinutes() seconds = now.getSeconds() hCenter = xyFromBase(hours, hRadius, 12) hCenter[0] += faceCenter[0] hCenter[1] += faceCenter[1] hourCircle .transition(d3.easeLinear) .duration(100) .attr('cx', hCenter[0]) .attr('cy', hCenter[1]) mCenter = xyFromBase(minutes, mRadius, 60) mCenter[0] += hCenter[0] mCenter[1] += hCenter[1] minuteCircle .transition(d3.easeLinear) .duration(100) .attr('cx', mCenter[0]) .attr('cy', mCenter[1]) sCenter = xyFromBase(seconds, sRadius, 60) sCenter[0] += mCenter[0] sCenter[1] += mCenter[1] secondCircle .transition(d3.easeLinear) .duration(500) .attr('cx', sCenter[0]) .attr('cy', sCenter[1]) } setInterval(function() { updateClock() }, 1000) //-------------------------------------------------- // TIME TEXT //-------------------------------------------------- const timeText = [ { value: 0, size: 0, label: '', update: function(date) { return `${addZeroBefore(date.getHours() % 12)}:${addZeroBefore( date.getMinutes() )}:${addZeroBefore(date.getSeconds())}` }, }, ] //add the time in text addZeroBefore = time => { return (time < 10 ? '0' : '') + time } let field = svg .selectAll('.field') .data(timeText) .enter() .append('g') .attr('class', 'field') let label = field .append('text') .attr('x', 40) .attr('y', height - 40) .attr('font-size', '20px') .attr('font-family', 'sans-serif') .style('fill', 'rgb(92, 94, 96)') .attr('class', 'label') function updateTime() { let now = new Date() field.each(function(d) { ;(d.previous = d.value), (d.value = d.update(now)) }) label.text(function(d) { return d.value + d.label }) label .transition(d3.easeLinear) .style('fill', 'white') .duration(1000) } setInterval(function() { updateTime() }, 1000) </script> </body>
https://d3js.org/d3.v4.min.js