Skip to content

Instantly share code, notes, and snippets.

@hharzer
Last active September 21, 2024 01:54
Show Gist options
  • Save hharzer/0d0658ee3027f5e63cc49ac06e40d6ab to your computer and use it in GitHub Desktop.
Save hharzer/0d0658ee3027f5e63cc49ac06e40d6ab to your computer and use it in GitHub Desktop.
SVG Working Clock
<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>
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();
<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>
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;
}
}

SVG Working Clock

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)

A Pen by hharzer on CodePen.

License.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment