Built with blockbuilder.org
forked from lbrucel's block: concentric clock d3.js
xxxxxxxxxx
<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