SVG Clock animated to give the current time. Small digital clock sitting below it showing the time. Used the TweenMax library. Code still needs to be cleaned a little bit (part of the Math is slightly altered to ensure that seconds are not delayed due to the animation)
Last active
September 21, 2024 01:54
-
-
Save hharzer/0d0658ee3027f5e63cc49ac06e40d6ab to your computer and use it in GitHub Desktop.
SVG Working Clock
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="clocks"> | |
<svg viewBox="-1024 -1024 2048 2048" class="clock"> | |
<title>Swiss Railway Clock</title> | |
<style type="text/css"> | |
.bg { | |
stroke: none; | |
fill: white; | |
} | |
.fc { | |
stroke: none; | |
fill: black; | |
} | |
.h1 { | |
stroke: none; | |
fill: black; | |
} | |
.h2 { | |
stroke: none; | |
fill: #333; | |
} | |
.h3 { | |
stroke: none; | |
fill: #aa0000; | |
} | |
</style> | |
<defs> | |
<path id="mark1" d="M -20,-1000 l 40,0 0,100 -40,0 z" /> | |
<path id="mark2" d="M -40,-1000 l 80,0 0,240 -80,0 z" /> | |
<path id="mark3" d="M -40,-1000 l 80,0 0,300 -80,0 z" /> | |
<path id="handh" d="M -50,-600 l 50,-50 50,50 0,800 -100,0 z" /> | |
<path id="handm" d="M -40,-900 l 40,-40 40,40 0,1180 -80,0 z" /> | |
<g id="hands"> | |
<path d="M -10,-910 l 10,-10 10,10 2,300 -24,0 z | |
M -13,-390 l 26,0 7,690 -40,0 z" /> | |
<path d="M 0,-620 a 120,120 0 0 1 0,240 | |
a 120,120 0 0 1 0,-240 z | |
M 0,-560 a 60,60 0 0 0 0,120 | |
a 60,60 0 0 0 0,-120 z" /> | |
</g> | |
<g id="face1"> | |
<use xlink:href="#mark1" transform="rotate(06)" /> | |
<use xlink:href="#mark1" transform="rotate(12)" /> | |
<use xlink:href="#mark1" transform="rotate(18)" /> | |
<use xlink:href="#mark1" transform="rotate(24)" /> | |
</g> | |
<g id="face2"> | |
<use xlink:href="#face1" /> | |
<use xlink:href="#face1" transform="rotate(30)" /> | |
<use xlink:href="#face1" transform="rotate(60)" /> | |
<use xlink:href="#mark3" /> | |
<use xlink:href="#mark2" transform="rotate(30)" /> | |
<use xlink:href="#mark2" transform="rotate(60)" /> | |
</g> | |
<g id="face"> | |
<use xlink:href="#face2" /> | |
<use xlink:href="#face2" transform="rotate(90)" /> | |
<use xlink:href="#face2" transform="rotate(180)" /> | |
<use xlink:href="#face2" transform="rotate(270)" /> | |
</g> | |
</defs> | |
<circle class="bg" r="1024" /> | |
<use xlink:href="#face" class="fc" /> | |
<use xlink:href="#handm" class="h2 minutes" transform="rotate(54)" /> | |
<use xlink:href="#handh" class="h1 hours" transform="rotate(304.5)" /> | |
<use xlink:href="#hands" class="h3 seconds" transform="rotate(12)" /> | |
<!-- hands at 10:09:02 --> | |
</svg> | |
<div class="digital-clock"> | |
<span class="digital-hours"></span>: | |
<span class="digital-minutes"></span>: | |
<span class="digital-seconds"></span> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const DEGREES = 360; | |
const SEC_IN_MIN = 60; | |
const MIN_IN_HOUR = 60; | |
const HOUR_IN_LOOP = 12; | |
const SEC_IN_HOURS = 3600; | |
const DEGREES_PER_MIN = DEGREES / MIN_IN_HOUR; | |
const DEGREES_PER_HOUR = DEGREES / HOUR_IN_LOOP; | |
const SECOND_DEGREES_PER_SECOND = DEGREES / SEC_IN_MIN; | |
const MINUTE_DEGREES_PER_SECOND = SECOND_DEGREES_PER_SECOND / MIN_IN_HOUR; | |
const HOUR_DEGREES_PER_SECOND = MINUTE_DEGREES_PER_SECOND / HOUR_IN_LOOP; | |
let tl = new TimelineMax(); | |
let moveSeconds = () => { | |
TweenMax.to(".seconds", 1, { | |
rotation: "+=" + SECOND_DEGREES_PER_SECOND, | |
onComplete: () => { | |
moveSeconds(); | |
} | |
}); | |
}; | |
let moveMinutes = () => { | |
TweenMax.to(".minutes", 1, { | |
rotation: "+=" + MINUTE_DEGREES_PER_SECOND, | |
onComplete: () => { | |
moveMinutes(); | |
} | |
}); | |
}; | |
let moveHours = () => { | |
TweenMax.to(".hours", 1, { | |
rotation: "+=" + HOUR_DEGREES_PER_SECOND, | |
onComplete: () => { | |
moveHours(); | |
} | |
}); | |
}; | |
let getCurrentTime = () => { | |
let t = new Date(); | |
let hours = t.getHours() % 12; | |
hours = hours ? hours : 12; | |
return { | |
hours: hours >= 10 ? hours : "0" + hours, | |
minutes: t.getMinutes() >= 10 ? t.getMinutes() : "0" + t.getMinutes(), | |
seconds: t.getSeconds() >= 10 ? t.getSeconds() : "0" + t.getSeconds() | |
}; | |
}; | |
const $digitalClock = $(".digital-clock"); | |
let $hours = $(".digital-hours"); | |
let $minutes = $(".digital-minutes"); | |
let $seconds = $(".digital-seconds"); | |
let updateDigitalClock = (time) => { | |
$hours.text(time.hours); | |
$minutes.text(time.minutes); | |
$seconds.text(time.seconds); | |
}; | |
let startClocks = () => { | |
let t = getCurrentTime(); | |
let intHours = parseInt(t.hours, 10); | |
let intMins = parseInt(t.minutes, 10); | |
let intSecs = parseInt(t.seconds, 10); | |
let secDegrees = | |
intSecs * SECOND_DEGREES_PER_SECOND - SECOND_DEGREES_PER_SECOND; | |
let minDegrees = (intMins + intSecs / SEC_IN_MIN) * DEGREES_PER_MIN; | |
let hourDegrees = | |
(intHours + intMins / MIN_IN_HOUR + intSecs / SEC_IN_HOURS) * | |
DEGREES_PER_HOUR; | |
// Setting load time on Digital Clock | |
updateDigitalClock(t); | |
// Setting load time on Analog Clock | |
TweenMax.set(".seconds", { | |
svgOrigin: "1 1", | |
rotation: secDegrees | |
}); | |
TweenMax.set(".minutes", { | |
svgOrigin: "0 0", | |
rotation: minDegrees | |
}); | |
TweenMax.set(".hours", { | |
svgOrigin: "0 0", | |
rotation: hourDegrees | |
}); | |
// Starting Analog Clock | |
moveSeconds(); | |
moveMinutes(); | |
moveHours(); | |
// Starting Digital Clock | |
setInterval(function () { | |
t = getCurrentTime(); | |
updateDigitalClock(t); | |
}, 1000); | |
}; | |
startClocks(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> | |
<script src="https://unpkg.co/gsap@3/dist/gsap.min.js"></script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
background: #333; | |
} | |
.clocks { | |
position: absolute; | |
left: 50%; | |
top: 50%; | |
transform: translate(-50%, -50%); | |
box-sizing: border-box; | |
width: min(40%, 300px); | |
height: min(40%, 300px); | |
text-align: center; | |
.clock { | |
border: 0px grey solid; | |
border-radius: 1rem; | |
width: 100%; | |
} | |
.clock:hover { | |
outline: 1px solid red; | |
} | |
.digital-clock { | |
display: none; | |
font-family: "Orbitron", sans-serif; | |
text-align: center; | |
color: #66cd00; | |
font-size: 35px; | |
width: 100%; | |
margin-top: 25px; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment