JS: SVG Clock

By Xah Lee. Date: . Last updated: .

Here's a how to write to write a analog clock in JavaScript, without library or framework.

HTML code:

<div id="svg_clock_68390"></div>
<script defer src="svg_clock.js"></script>

Here's JavaScript code.

{
// 2015-04-04 copyright 2015, 2018 Xah Lee.
// keep this section
// http://xahlee.info/js/svg_clock.html
// version 2019-04-25

const hour_hand_length = 0.45; // ratio to radius of clock
const minute_hand_length = 0.7; // ratio to radius of clock
const sec_hand_length = 0.9; // ratio to radius of clock

// create a svg tag
const svg_container = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg_container.setAttribute("viewBox", "-1 -1 2 2");

const clock_frame = document.createElementNS("http://www.w3.org/2000/svg", "circle");
clock_frame.setAttribute("cx", "0");
clock_frame.setAttribute("cy", "0");
clock_frame.setAttribute("r", ".97");
clock_frame.setAttribute("style", "fill:none;stroke:black; stroke-width:2%");
svg_container.appendChild(clock_frame);

// draw second marks
for (let ii = 0;ii < 60; ii++) {
    const jj = 2 * Math.PI / 60 *ii;
    const sec_pos = document.createElementNS("http://www.w3.org/2000/svg", "circle");
    sec_pos.setAttribute("cx", (Math.cos(jj)*.9) .toString ());
    sec_pos.setAttribute("cy", (Math.sin(jj)*.9) .toString ());
    sec_pos.setAttribute("r", "0.8%");
    sec_pos.setAttribute("style", "fill:grey;stroke:none;");
    svg_container.appendChild(sec_pos);
};

// draw hour marks
for (let ii = 0;ii < 12; ii++) {
    const jj = 2 * Math.PI / 12 *ii;
    const hour_pos = document.createElementNS("http://www.w3.org/2000/svg", "circle");
    hour_pos.setAttribute("cx", (Math.cos(jj)*.9) .toString ());
    hour_pos.setAttribute("cy", (Math.sin(jj)*.9) .toString ());
    hour_pos.setAttribute("r", "3%");
    hour_pos.setAttribute("style", "fill:black;stroke:none;");
    svg_container.appendChild(hour_pos);
};

// hour hand
const hour_hand = document.createElementNS("http://www.w3.org/2000/svg", "line");
hour_hand.setAttribute("x1", "0");
hour_hand.setAttribute("y1", "0");
hour_hand.setAttribute("x2", "0");
hour_hand.setAttribute("y2", (-1 * hour_hand_length) .toString ());
hour_hand.setAttribute("style", "stroke:blue; stroke-width:5%;stroke-linecap:round");
hour_hand.setAttribute("transform", "rotate(" + (((new Date()).getHours() % 12) * 30 + (new Date()).getMinutes() /2) +  ")");
svg_container.appendChild(hour_hand);

// minute hand
const minute_hand = document.createElementNS("http://www.w3.org/2000/svg", "line");
minute_hand.setAttribute("x1", "0");
minute_hand.setAttribute("y1", "0");
minute_hand.setAttribute("x2", "0");
minute_hand.setAttribute("y2", (-1 * minute_hand_length) .toString ());
minute_hand.setAttribute("style", "stroke:red; stroke-width:3%;stroke-linecap:round");
minute_hand.setAttribute("transform", "rotate(" + ((new Date()).getMinutes()*6) +  ")");
svg_container.appendChild(minute_hand);

const sec_hand = document.createElementNS("http://www.w3.org/2000/svg", "line");
sec_hand.setAttribute("x1", "0");
sec_hand.setAttribute("y1", "0");
sec_hand.setAttribute("x2", "0");
sec_hand.setAttribute("y2", (-1 * sec_hand_length) .toString ());
sec_hand.setAttribute("style", "stroke:black; stroke-width:1%;stroke-linecap:round");
sec_hand.setAttribute("transform", "rotate(" + ((new Date()).getSeconds()*6) +  ")");
svg_container.appendChild(sec_hand);

// const f_update_clock = (() => {
//     const dd = new Date();
//     sec_hand.setAttribute("transform", "rotate(" + (dd.getSeconds()*6) +  ")");
//     minute_hand.setAttribute("transform", "rotate(" + (dd.getMinutes()*6) +  ")");
//     hour_hand.setAttribute("transform", "rotate(" + ((dd.getHours() % 12) * 30 + dd.getMinutes() /2) +  ")");
// });

const f_update_clock2 = ((dt) => {
    const dd = new Date(performance.timing.navigationStart + dt);
    sec_hand.setAttribute("transform", "rotate(" + (dd.getSeconds()*6 + (dd.getMilliseconds()*6/1000)).toString() +  ")");
    minute_hand.setAttribute("transform", "rotate(" + (dd.getMinutes()*6) +  ")");
    hour_hand.setAttribute("transform", "rotate(" + ((dd.getHours() % 12) * 30 + dd.getMinutes() /2) +  ")");
});

const newNode = document .createElement("div");
newNode.style.maxWidth= "300px";
newNode. appendChild(svg_container);
document.currentScript. insertAdjacentElement("afterend", newNode);

// setInterval( f_update_clock , 1000);
setInterval( (() => { requestAnimationFrame(f_update_clock2) }) , 1000/20);

}

Digital Clock

JS: Digital Clock

SVG tutorial

  1. SVG Basics
  2. Path
  3. Path Elliptical Arc
  4. Specifying Styles
  5. Shape Styles
  6. Viewport
  7. viewBox
  8. Coordinate Transformation
  9. Text Element
  10. Font Size
  11. Structure Elements
  12. Scripting SVG
  13. SVG Clock
  14. Animation
Liket it? I spend 2 years writing this tutorial. Help me spread it. Tell your friends. Or, Put $5 at patreon.

Or, Buy JavaScript in Depth

If you have a question, put $5 at patreon and message me.

SVG tutorial

  1. SVG Basics
  2. Path
  3. Path Elliptical Arc
  4. Specifying Styles
  5. Shape Styles
  6. Viewport
  7. viewBox
  8. Coordinate Transformation
  9. Text Element
  10. Font Size
  11. Structure Elements
  12. Scripting SVG
  13. SVG Clock
  14. Animation

Canvas Intro

  1. Canvas vs SVG
  2. Canvas intro
  3. Demo: Halma
  4. Demo: Raycaster