Skip to content

Instantly share code, notes, and snippets.

@IOIO72
Last active March 31, 2020 00:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save IOIO72/d283030bf0614014eba88be59cc7acff to your computer and use it in GitHub Desktop.
Save IOIO72/d283030bf0614014eba88be59cc7acff to your computer and use it in GitHub Desktop.
Clock [WIP]
<div id="root"></div>
const {useState, useCallback, useEffect, useRef } = React;
const DebugClock = props => (
<table className="debug-clock">
{Object.entries(props).map(item => (
<tr key={item[0]} className="debug-clock__property">
<td className="debug-clock__key">{item[0]}</td>
<td className="debug-clock__value">{item[1]}</td>
</tr>
))}
</table>
);
const Hand = ({type = 'hours', degrees}) => (
<div className={`hand hand--${type}`} style={{
transform: `rotateZ(${degrees}deg)`
}} />
);
const AnalogClock = ({hrs,mr,mrs,srs,sr,smoothMinutes=false,smoothSeconds=false}) => {
return (
<div className="analog-clock">
<div className="analog-clock__face">
<Hand type="hours" degrees={hrs} />
<Hand type="minutes" degrees={smoothMinutes ? mrs : mr} />
<Hand type="seconds" degrees={smoothSeconds ? srs : sr} />
</div>
</div>
);
}
const DigitalClock = ({h0,h024,m0,s0,ampm,mode24=false,blink=false,lcd=false}) => (
<time className={`digital-clock digital-clock--${lcd ? 'lcd' : 'text' }`}>
<span className="digital-clock__hours">{mode24 ? h024 : h0}</span>
<span className={`digital-clock__divider digital-clock__divider--${blink ? 'blink' : 'static'}`}>:</span>
<span className="digital-clock__minutes">{m0}</span>
<span className={`digital-clock__divider digital-clock__divider--${blink ? 'blink' : 'static'}`}>:</span>
<span className="digital-clock__seconds">{s0}</span>
{!mode24 && (
<span className="digital-clock__ampm">{ampm}</span>
)}
</time>
)
const Clock = ({
type = 'digital',
scale = 1,
delay = 250,
className = '',
...otherProps
}) => {
const clockElement = useRef(null);
const [time, setTime] = useState({h:0,h24:0,m:0,s:0,ms:0,h0:'00',h024:'00',m0:'00',s0:'00',hr:0,hr24:0,mr:0,sr:0,hrs:0,hrs24:0,mrs:0,srs:0,ampm:'',});
const getTwoDigits = num => `${num < 10 ? '0' : ''}${num}`;
const getRotationValue = (units, value, smoothDegrees = false) => {
const degrees = 360 / units;
const rotation = value * degrees;
const smoothRotation = smoothDegrees === false
? 0
: smoothDegrees / 360 * degrees;
return rotation + smoothRotation;
}
const ts = new Date();
const currentTime = useCallback(() => {
const hours24 = ts.getHours();
const hours = hours24 % 12;
const minutes = ts.getMinutes();
const seconds = ts.getSeconds();
const milliseconds = ts.getMilliseconds();
setTime({
h: hours,
h24: hours24,
h0: getTwoDigits(hours),
h024: getTwoDigits(hours24),
hr: getRotationValue(12, hours),
hrs: getRotationValue(12, hours, getRotationValue(60, minutes)),
hr24: getRotationValue(24, hours24),
hrs24: getRotationValue(24, hours24, getRotationValue(60, minutes)),
m: minutes,
m0: getTwoDigits(minutes),
mr: getRotationValue(60, minutes),
mrs: getRotationValue(60, minutes, getRotationValue(60, seconds)),
s: seconds,
s0: getTwoDigits(seconds),
sr: getRotationValue(60, seconds),
srs: getRotationValue(60, seconds, getRotationValue(1000, milliseconds)),
ms: milliseconds,
ampm: hours24 > 11 ? 'pm' : 'am',
});
}, [ts, setTime, getTwoDigits, getRotationValue]);
useEffect(() => {
const interval = setInterval(() => {
currentTime();
}, delay);
return () => clearInterval(interval);
}, [currentTime, delay]);
useEffect(() => {
if (clockElement.current && scale && scale !== 1) {
clockElement.current.setAttribute("style", `
width: ${clockElement.current.offsetWidth * scale}px;
height: ${clockElement.current.offsetHeight * scale}px;
transform: scale(${scale});
`);
}
}, [scale, clockElement]);
return (
<div ref={clockElement} className={`clock ${className}`}>
{type === 'digital' && <DigitalClock {...time} {...otherProps} />}
{type === 'analog' && <AnalogClock {...time} {...otherProps} />}
{type === 'debug' && <DebugClock {...time} {...otherProps} />}
</div>
);
};
const App = () => (
<>
<Clock type="digital" />
<Clock type="digital" mode24 blink />
<Clock type="digital" scale={2.5} lcd blink className="color__blue" /><br />
<Clock type="analog" />
<Clock type="analog" delay={50} smoothMinutes smoothSeconds />
<Clock type="analog" scale={0.25} delay={200} smoothSeconds />
<Clock type="debug" delay={200} />
</>
);
ReactDOM.render(
<App />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
@import url(https://db.onlinewebfonts.com/c/1cb7c6ea746ff369304a02b0538ce0f1?family=LCD);
@font-face {font-family: "LCD"; src: url("https://db.onlinewebfonts.com/t/1cb7c6ea746ff369304a02b0538ce0f1.eot"); src: url("https://db.onlinewebfonts.com/t/1cb7c6ea746ff369304a02b0538ce0f1.eot?#iefix") format("embedded-opentype"), url("https://db.onlinewebfonts.com/t/1cb7c6ea746ff369304a02b0538ce0f1.woff2") format("woff2"), url("https://db.onlinewebfonts.com/t/1cb7c6ea746ff369304a02b0538ce0f1.woff") format("woff"), url("https://db.onlinewebfonts.com/t/1cb7c6ea746ff369304a02b0538ce0f1.ttf") format("truetype"), url("https://db.onlinewebfonts.com/t/1cb7c6ea746ff369304a02b0538ce0f1.svg#LCD") format("svg"); }
$analog: (
size: 32rem,
hub: 3rem,
hand-color: #05134f,
hand-accent-color: #bd0000,
hours-width: 1.625rem,
hours-height: 9.625rem,
minutes-width: 1.25rem,
minutes-height: 14.75rem,
seconds-width: 0.5rem,
seconds-height: 15.125rem,
);
@keyframes blink {
0% {opacity:0;}
50% {opacity:1;}
100% {opacity:0;}
}
.clock {
display: inline-block;
transform-origin: left top;
}
.debug-clock {
font-family: monospace;
background-color: black;
color: white;
&__key {
color: cyan;
text-align: right;
}
&__value {
color: lime;
text-align: left;
}
}
.digital-clock {
display: inline-block;
padding: 0.5rem;
font-family: monospace;
&--lcd {
font-family: LCD, monospace;
text-transform: uppercase;
}
&__divider {
opacity: 1;
&--blink {
animation: {
name: blink;
duration: 1s;
iteration-count: infinite;
};
}
}
&__ampm {
margin-left: 0.25rem;
}
}
.analog-clock {
display: inline-block;
&__face {
width: map-get($analog, size);
height: map-get($analog, size);
position: relative;
display: flex;
justify-content: center;
border-radius: 50%;
background-color: lightgray;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='512' height='512' viewBox='0 0 5120 5120'%3E%3Cg fill='%23061350'%3E%3Cpath d='M2297 4963c-44-4-48-6-44-26 3-12 9-61 13-109l7-88h31c17 0 42 3 55 7 23 6 23 7 17 92-8 95-15 132-25 129-3-1-28-3-54-5zM2460 4590v-380h200v760h-200v-380zM2756 4946c-3-12-8-60-12-107-6-85-6-86 17-92 13-4 38-7 55-7h30l11 108c6 59 10 108 9 108 0 1-24 4-53 6-46 4-52 3-57-16zM2047 4923c-37-6-41-20-27-90 29-144 28-143 101-123l37 10-22 103c-24 110-24 110-89 100zM3006 4918c-3-7-14-55-24-105l-20-93 37-10c60-17 69-13 80 28 22 84 33 164 25 172-5 4-28 11-51 15-32 5-44 3-47-7zM1805 4855c-31-9-39-17-37-31 7-34 54-179 61-187 10-10 101 22 101 36 0 29-63 197-73 196-7-1-30-7-52-14zM3221 4777c-17-50-31-97-31-104 0-14 91-46 101-36 7 8 54 153 61 187 2 14-7 21-42 32-25 8-48 14-52 14-3 0-20-42-37-93zM1577 4768c-26-11-47-24-47-28s19-50 43-103l44-96 51 24 51 24-43 96c-24 52-45 97-47 100-2 2-26-6-52-17zM3481 4768c-5-13-25-58-45-101l-35-78 51-24 51-24 44 96c48 107 48 109 31 116-7 3-30 12-51 21-37 16-38 16-46-6zM1350 4651c-47-27-84-53-83-58 4-21 302-528 311-531 8-2 140 66 180 93 5 4-310 545-317 545-3 0-44-22-91-49zM3516 4429c-86-150-155-273-154-274 40-27 172-95 180-93 9 3 307 510 311 531 2 8-159 107-174 107-4 0-77-122-163-271zM1137 4513c-20-14-37-29-37-33 0-11 119-170 128-170 16 0 83 52 80 62-8 23-114 167-123 168-6 0-27-12-48-27zM3870 4458c-33-45-60-85-60-89 0-9 70-59 82-59 9 0 128 159 128 170 0 8-72 60-83 60-4 0-34-37-67-82zM946 4359c-20-17-36-36-36-41 0-13 130-158 141-158 5 0 26 15 46 34l37 34-62 69c-90 102-84 99-126 62zM4059 4309l-73-81 37-34c20-19 41-34 46-34 11 0 141 145 141 158 0 9-65 72-74 72-2 0-37-37-77-81zM761 4175c-17-20-31-37-31-39s37-37 81-77l81-73 34 37c19 20 34 41 34 46 0 11-145 141-158 141-5 0-24-16-41-35zM4231 4142c-81-74-82-80-27-131l25-24 81 73c44 40 80 74 80 76 0 10-64 74-74 74-6-1-44-31-85-68zM604 3979l-29-42 33-27c79-66 142-103 155-91 17 13 53 79 47 84-35 27-154 109-164 113-7 3-26-14-42-37zM4405 3969c-39-27-77-54-85-59-13-8-13-13 4-45 33-60 40-62 100-20 30 20 69 50 88 65l33 27-29 42c-16 22-32 41-35 41-4 0-38-23-76-51zM482 3793c-59-102-65-114-55-123 13-12 536-311 538-308 26 39 95 172 93 179-2 6-105 69-228 141-124 71-244 140-267 154l-42 24-39-67zM4330 3705c-145-84-266-158-268-163-2-8 67-141 93-180 3-3 525 296 539 309 8 7-54 130-86 171-12 15-38 2-278-137zM357 3553c-9-21-18-44-19-51-2-7 38-31 95-57l98-44 24 51 24 51-96 44c-53 24-99 43-103 43s-14-17-23-37zM4633 3546l-92-42 24-52 24-51 98 44c57 26 97 50 95 57-7 33-36 88-46 87-6 0-52-20-103-43zM275 3347c-2-7-8-27-14-46s-11-37-11-42c0-7 175-69 197-69 8 0 43 77 43 97 0 5-35 18-129 46-58 18-83 22-86 14zM4740 3328c-52-16-98-33-103-37-10-10 22-101 37-101 13 0 187 57 193 64 5 5-18 88-26 97-3 4-49-7-101-23zM205 3098c-3-7-6-31-8-52l-2-40 102-22 103-22 10 37c20 73 23 70-98 96-89 18-101 19-107 3zM4820 3098c-131-28-130-27-110-99l10-37 103 22 102 22-2 40c-5 70-10 72-103 52zM158 2818c-2-29-3-55-1-57 5-8 203-25 209-18 4 4 9 28 12 55l4 49-88 7c-49 4-99 10-110 12-20 5-22 1-26-48zM4836 2857l-98-10 4-49c3-27 8-51 12-55 6-7 204 10 209 18 9 12-6 109-16 107-7 0-56-6-111-11zM150 2560v-100h760v200H150v-100zM4210 2560v-100h760v200h-760v-100zM217 2370c-32-4-59-9-60-11-2-2-1-28 1-57 4-49 6-53 26-48 11 2 60 8 109 12l87 7v31c0 66-8 76-59 75-25-1-72-5-104-9zM4747 2359c-4-13-7-38-7-55v-30l108-11c59-6 108-10 108-9 1 0 4 24 6 53 6 60 10 58-123 69-85 6-86 6-92-17zM295 2135l-100-21 3-45c2-24 7-48 12-53 8-8 88 3 174 25 38 10 38 11 32 51-11 67-10 67-121 43zM4710 2121c-17-60-13-69 28-80 84-22 164-33 172-25 5 5 10 29 12 53l3 45-102 22-103 22-10-37zM341 1899c-46-16-86-30-88-33-2-2 2-26 10-52 11-39 18-48 33-46 34 7 179 54 187 61 13 13-23 101-41 100-10 0-55-14-101-30zM4646 1883c-9-26-13-50-9-54 8-7 153-54 187-61 14-2 21 7 32 42 8 25 14 48 14 52 0 7-176 68-197 68-6 0-18-21-27-47zM692 1606c-144-85-265-156-268-159-6-6 62-135 88-169 12-15 38-2 278 137 145 84 266 158 268 163 3 11-89 182-98 181-3 0-123-69-268-153zM4107 1674c-26-47-47-90-45-96 2-5 123-79 268-163 240-139 266-152 278-137 32 41 94 164 86 171-9 8-534 311-537 311-1 0-24-39-50-86zM430 1674c-55-25-94-49-92-56 5-26 35-88 42-88 4 0 50 19 103 43l96 44-24 51c-13 29-25 52-27 51-2 0-46-21-98-45zM4565 1668l-24-51 96-44c53-24 99-43 103-43 7 0 37 62 42 88 2 7-38 31-95 57l-98 44-24-51zM662 1250c-45-33-82-63-82-67 0-11 52-83 60-83 11 0 170 119 170 128 0 12-50 82-59 82-4 0-44-27-89-60zM4335 1273c-14-21-25-41-25-45 0-9 159-128 170-128 8 0 60 72 60 83 0 9-160 127-171 127-5 0-20-17-34-37zM806 1057l-79-73 33-37c17-20 37-37 42-37 13 0 158 130 158 141 0 10-60 79-69 79-3 0-42-33-85-73zM4191 1095c-17-20-31-39-31-44 0-11 145-141 158-141 5 0 25 17 42 37l33 37-79 73c-43 40-82 73-85 73-4 0-21-16-38-35zM1567 1053c-85-145-299-519-300-526-2-8 159-107 174-107 7 0 322 541 317 545-28 19-170 95-177 95-5 0-12-3-14-7zM3450 1015c-41-25-79-46-83-48-7-2 281-515 304-541 7-8 130 54 171 86 15 12 2 38-137 278-84 146-159 266-167 267-7 1-47-18-88-42zM976 886c-36-41-66-78-66-84 0-9 65-72 74-72 2 0 37 37 77 81l73 81-37 34c-20 19-41 34-46 34s-38-33-75-74zM4023 926l-37-34 73-81c40-44 75-81 77-81 9 0 74 63 74 72 0 13-130 158-141 158-5 0-26-15-46-34zM2460 530V150h200v760h-200V530zM1160 728c-33-45-60-85-60-88 0-8 72-60 83-60 9 0 127 160 127 171 0 9-70 59-82 59-5 0-35-37-68-82zM3847 785c-20-14-37-29-37-34 0-11 118-171 127-171 11 0 83 52 83 60 0 11-119 170-128 170-4 0-24-11-45-25zM1572 481c-23-53-42-99-42-102 0-6 64-36 88-41 7-2 31 38 56 95l45 97-30 15c-75 39-70 42-117-64zM3452 555l-51-24 44-98c26-57 50-97 57-95 26 5 88 35 88 42 0 4-19 50-43 103l-44 96-51-24zM1821 467c-34-88-59-188-48-192 7-2 27-8 46-14s37-11 42-11c7 0 69 175 69 197 0 6-21 18-47 27-57 20-52 20-62-7zM3233 473c-24-8-43-20-43-26 0-21 61-197 68-197 4 0 27 6 52 14 37 11 44 17 42 34-6 40-58 186-68 188-5 1-28-4-51-13zM2041 383c-22-85-33-165-25-173 5-5 29-10 53-12l45-3 22 102 22 103-37 10c-60 17-69 13-80-27zM2994 409l-32-9 22-102 22-103 45 3c24 2 48 7 53 12 8 8-3 88-25 173-11 40-23 44-85 26zM2263 273c-6-60-10-109-9-109 0-1 24-4 53-6 60-6 58-10 69 123 6 85 6 86-17 92-13 4-38 7-55 7h-30l-11-107zM2756 373c-17-5-18-12-12-91 11-134 9-130 69-124 29 2 53 5 53 6 1 0-3 49-9 109l-11 107-35-1c-20-1-44-3-55-6z'/%3E%3C/g%3E%3C/svg%3E");
background-size: cover;
background-repeat: no-repeat;
&::after {
width: map-get($analog, hub);
height: map-get($analog, hub);
background-color: map-get($analog, hand-color);
position: absolute;
display: inline-block;
content: '';
border-radius: 50%;
top: 50%;
transform: translateY(-50%);
}
}
}
%hand-shadow {
box-shadow: 0 0 8px -1px black;
}
%hand-shadow-in {
box-shadow: inset 0 0 6px -1px black, 0 0 6px -1px black;
}
.hand {
@extend %hand-shadow;
width: map-get($analog, hours-width);
height: map-get($analog, hours-height);
background-color: map-get($analog, hand-color);
position: absolute;
display: flex;
justify-content: center;
bottom: 50%;
transform-origin: bottom center;
&--hours {
width: map-get($analog, hours-width);
height: map-get($analog, hours-height);
}
&--minutes {
width: map-get($analog, minutes-width);
height: map-get($analog, minutes-height);
}
&--seconds {
width: map-get($analog, seconds-width);
height: map-get($analog, seconds-height) * 0.4;
background-color: map-get($analog, hand-accent-color);
&::before {
@extend %hand-shadow-in;
border: map-get($analog, seconds-width) * 0.9 solid map-get($analog, hand-accent-color);
width: map-get($analog, hub);
height: map-get($analog, hub);
position: absolute;
display: inline-block;
content: '';
border-radius: 50%;
background-color: transparent;
left: 50%;
top: 0;
transform: translate(-50%, -100%);
}
&::after {
@extend %hand-shadow;
width: map-get($analog, seconds-width) * 0.8;
height: map-get($analog, seconds-height) * 0.3 + map-get($analog, seconds-width) * 1.2;
top: (map-get($analog, seconds-height) * 0.4 + map-get($analog, hub)) * -1;
background-color: map-get($analog, hand-accent-color);
position: absolute;
display: inline-block;
content: '';
}
}
}
.color {
&__black {
color: #000000;
}
&__white {
color: #ffffff;
}
&__red {
color: #bd0000;
}
&__blue {
color: #0513af;
&--dark {
color: #05134f;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment