<div id="chooser">
</div>
<div class="fill">
<div class="clock
hour-style-pill
hour-text-style-large
hour-display-style-all
minute-style-line
minute-display-style-fine-2
minute-text-style-outside
hand-style-hollow
" id="utility-clock">
<div class="centre">
<div class="dynamic"></div>
<div class="expand round circle-1"></div>
<div class="anchor hour">
<div class="element thin-hand"></div>
<div class="element fat-hand"></div>
</div>
<div class="anchor minute">
<div class="element thin-hand"></div>
<div class="element fat-hand minute-hand"></div>
</div>
<div class="anchor second">
<div class="element second-hand second-hand-front"></div>
<div class="element second-hand second-hand-back"></div>
</div>
<div class="expand round circle-2"></div>
</div>
</div>
</div>
body {
background: black;
}
.fill {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.clock {
position: absolute;
opacity: 1;
left: 50%;
top: 50%;
}
.centre {
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
}
.expand {
position: absolute;
top: 0;
left: 0;
transform: translate(-50%, -50%);
}
.anchor {
position: absolute;
top: 0;
left: 0;
width: 0;
height: 0;
}
.element {
position: absolute;
top: 0;
left: 0;
}
.round {
border-radius: 296px;
}
.circle-1 {
width: 6px;
height: 6px;
border: 3px solid white;
}
.circle-2 {
width: 4px;
height: 4px;
border: 2px solid #FA9F22;
}
.second {
transform: rotate(180deg);
}
.minute {
transform: rotate(54deg);
}
.second-hand {
width: 2px;
background: #FA9F22;
}
.second-hand-front {
width: 2px;
height: 137px;
background: #FA9F22;
transform: translate(-50%,-100%) translateY(-3px);
}
.second-hand-back {
width: 2px;
height: 21px;
background: #FA9F22;
opacity: 1;
transform: translate(-50%,-100%) translateY(24px);
}
.hour {
transform: rotate(304.5deg);
}
.thin-hand {
width: 4px;
height: 50px;
background: white;
transform: translate(-50%,-100%) translateY(-5px);
}
.fat-hand {
box-sizing: border-box;
width: 10px;
height: 57px;
border-radius: 10px;
background: white;
transform: translate(-50%,-100%) translateY(-18px);
}
.minute-hand {
height: 112px;
}
.minute-line {
background: white;
width: 1px;
height: 9px;
transform: translate(-50%,-100%) translateY(-131px);
opacity: 0.34;
}
.major.minute-line {
opacity: 0.5;
}
.minute-text {
font: 12px Avenir Next, Helvetica;
color: white;
top: -135px;
}
.hour-pill {
background: white;
width: 6px;
height: 35px;
border-radius: 10px;
transform: translate(-50%,-100%) translateY(-85px);
opacity: 0.75;
}
.hour-text {
font: 40px Hei, Helvetica;
color: white;
top: -105px;
}
.hour-10 .content {
padding-left: 0.4ex;
}
.hour-11 .content {
padding-left: 0.25ex;
}
/* Now, customizations! */
/* Customize: hour */
.hour-style-text .hour-pill {
opacity: 0;
}
.hour-style-pill .hour-text {
opacity: 0;
}
.hour-style-text-quarters .hour-1.hour-text,
.hour-style-text-quarters .hour-2.hour-text,
.hour-style-text-quarters .hour-3.hour-pill,
.hour-style-text-quarters .hour-4.hour-text,
.hour-style-text-quarters .hour-5.hour-text,
.hour-style-text-quarters .hour-6.hour-pill,
.hour-style-text-quarters .hour-7.hour-text,
.hour-style-text-quarters .hour-8.hour-text,
.hour-style-text-quarters .hour-9.hour-pill,
.hour-style-text-quarters .hour-10.hour-text,
.hour-style-text-quarters .hour-11.hour-text,
.hour-style-text-quarters .hour-12.hour-pill {
opacity: 0;
}
/* Customize: hour-text */
.hour-text-style-small .hour-text {
font-size: 24px;
top: -113px;
}
/* Customize: hour-display */
.hour-display-style-quarters .hour-1,
.hour-display-style-quarters .hour-2,
.hour-display-style-quarters .hour-4,
.hour-display-style-quarters .hour-5,
.hour-display-style-quarters .hour-7,
.hour-display-style-quarters .hour-8,
.hour-display-style-quarters .hour-10,
.hour-display-style-quarters .hour-11 {
opacity: 0;
}
.hour-display-style-none .hour-item {
opacity: 0;
}
/* Customize: minute */
.minute-style-dot .minute-line {
width: 6px;
height: 6px;
transform: translate(-50%,-100%) translateY(-134px);
border-radius: 6px;
opacity: 0.75;
}
.minute-style-dot .part.minute-line,
.minute-style-dot.hour-style-pill .major.minute-line {
opacity: 0;
}
.minute-style-dot .hour-pill {
transform: translate(-50%,-100%) translateY(-100px);
height: 40px;
}
/* Customize: minute text */
.minute-text-style-inside .major.minute-line {
opacity: 0;
}
.minute-text-style-outside .minute-text {
top: -152px;
font-size: 14px;
}
.minute-text-style-none .minute-text {
opacity: 0;
}
/* Customize: Minute display */
.minute-style-line.minute-display-style-fine-2 .whole.minute-line,
.minute-style-line.minute-display-style-fine-2 .major.minute-line {
height: 13px;
transform: translate(-50%,-100%) translateY(-127px);
}
.minute-style-line.minute-display-style-fine-2 .part.minute-line {
height: 8px;
transform: translate(-50%,-100%) translateY(-132px);
}
.minute-display-style-coarse .part.minute-line {
opacity: 0;
}
.minute-display-style-major .part.minute-line,
.minute-display-style-major .whole.minute-line {
opacity: 0;
}
.minute-display-style-none .part.minute-line,
.minute-display-style-none .major.major.minute-line,
.minute-display-style-none .whole.minute-line {
opacity: 0;
}
/* Customize: hand */
.hand-style-hollow .fat-hand {
background: black;
border: 2px solid white;
}
/* Customizer */
#chooser {
font: 10px Verdana, sans-serif;
position: absolute;
top: 4px;
left: 4px;
color: white;
z-index: 1;
opacity: 0.5;
}
#chooser div {
cursor: pointer;
}
#chooser div:hover {
background: rgba(255,255,255,0.4);
}
var clock = document.querySelector('#utility-clock')
utilityClock(clock)
autoResize(clock, 295 + 32)
choose(clock, [
['hour', ['text', 'text-quarters', 'pill']],
['hour-text', ['large', 'small']],
['hour-display', ['all', 'quarters', 'none']],
['minute', ['line', 'dot']],
['minute-display', ['fine', 'fine-2', 'coarse', 'major', 'none']],
['minute-text', ['inside', 'outside', 'none']],
['hand', ['normal', 'hollow']]
])
function utilityClock(container) {
var dynamic = container.querySelector('.dynamic')
var hourElement = container.querySelector('.hour')
var minuteElement = container.querySelector('.minute')
var secondElement = container.querySelector('.second')
var div = function(className, innerHTML) {
var element = document.createElement('div')
element.className = className
element.innerHTML = innerHTML || ''
return element
}
var append = function(element) {
return {
to: function(parent) {
parent.appendChild(element)
return append(parent)
}
}
}
var anchor = function(element, rotation) {
var anchor = div('anchor')
rotate(anchor, rotation)
append(element).to(anchor).to(dynamic)
}
var minute = function(n) {
var klass = n % 5 == 0 ? 'major' : n % 1 == 0 ? 'whole' : 'part'
var line = div('element minute-line ' + klass)
anchor(line, n)
if (n % 5 == 0) {
var text = div('anchor minute-text ' + klass)
var content = div('expand content', (n < 10 ? '0' : '') + n)
append(content).to(text)
rotate(text, -n)
anchor(text, n)
}
}
var hour = function(n) {
var klass = 'hour-item hour-' + n
var line = div('element hour-pill ' + klass)
anchor(line, n * 5)
var text = div('anchor hour-text ' + klass)
var content = div('expand content', n)
append(content).to(text)
rotate(text, -n * 5)
anchor(text, n * 5)
return
}
var position = function(element, phase, r) {
var theta = phase * 2 * Math.PI
element.style.top = (-r * Math.cos(theta)).toFixed(1) + 'px'
element.style.left = (r * Math.sin(theta)).toFixed(1) + 'px'
}
var rotate = function(element, second) {
element.style.transform = element.style.webkitTransform = 'rotate(' + (second * 6) + 'deg)'
}
var animate = function() {
var now = new Date()
var time = now.getHours() * 3600 +
now.getMinutes() * 60 +
now.getSeconds() * 1 +
now.getMilliseconds() / 1000
rotate(secondElement, time)
rotate(minuteElement, time / 60)
rotate(hourElement, time / 60 / 12)
requestAnimationFrame(animate)
}
for (var i = 1 / 4; i <= 60; i += 1 / 4) minute(i)
for (var i = 1; i <= 12; i ++) hour(i)
animate()
}
function autoResize(element, nativeSize) {
var update = function() {
var parent = element.offsetParent
var scale = Math.min(parent.offsetWidth, parent.offsetHeight) / nativeSize
element.style.transform = element.style.webkitTransform = 'scale(' + scale.toFixed(3) + ')'
}
update()
window.addEventListener('resize', update)
}
function choose(clock, items) {
var chooser = document.querySelector('#chooser')
items.forEach(function(item) {
var name = item[0]
var styles = item[1]
var element = document.createElement('div')
element.addEventListener('click', click, false)
update()
chooser.appendChild(element)
function update() {
element.innerHTML = name + '-style-<b>' + getValue() + '</b>'
}
function klass(c) {
return name + '-style-' + c
}
function getValue() {
for (var i = 0; i < styles.length; i ++) {
if (clock.classList.contains(klass(styles[i]))) return styles[i]
}
}
function click(e) {
for (var i = 0; i < styles.length; i ++) {
if (clock.classList.contains(klass(styles[i]))) {
clock.classList.remove(klass(styles[i]))
clock.classList.add(klass(styles[(i + 1) % styles.length]))
break
}
}
update()
e.preventDefault()
}
})
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.