DEV Community

Cover image for Inspired by....

Posted on


Inspired by....

Inspired by a nice post Simple Analog Clock Using Html, CSS & Javascript, that shows how to build an analog clock the "traditional" way, I was curious to see, how much coding it would need with DML, the Document Makeup Library.

The original HTML-setup is very nice, but a bit lengthy. And it lacks some portability. So, here I show, how to set up a class with DML that gives you the same functionality. This can be used like any standard HTML element in DML or it can be provided as a WebComponent with minimal effort.

This is myclock.js:

// just a class wrapper for convenience
function myClock(size = 300, attrib) { return new _myClock(size, attrib) }

// the class
class _myClock  {
  constructor(size, attrib) {
    this.size = size
    const cx = size/2, cy = size/2;  // Radius
    const _clockstyle = "width: " + (size) + "px;  height: " + (size) + "px;"
      + "border: 7px solid #282828; background: #585858;"
      + "border-radius: 50%; margin: 50px;"
      + "box-shadow: -4px -4px 10px rgba(67,67,67,0.5), inset 4px 4px 10px rgba(0,0,0,0.5),"
      + "inset -4px -4px 10px rgba(67,67,67,0.5), 4px 4px 10px rgba(0,0,0,0.3);"

    this.base = sidiv("", _clockstyle+attrib)
    let c = this.canvas = canvas2D({ width: px(2 * cx), height: px(2 * cy) })

    c.ctx.lineCap = "round"

    // Paint anything radial
    function tick(color, width, angle, length, innerlength = 0) {
      function ls(length) { return length * Math.sin(angle / 180.0 * Math.PI) }
      function lc(length) { return -length * Math.cos(angle / 180.0 * Math.PI) }
      c.setLineType(width, color)
      c.line(cx + ls(innerlength), cy + lc(innerlength), cx + ls(length), cy + lc(length))

    // Draw clock
    function drawClock() {
      // Draw ticks
      for (let i = 0; i < 360; i += 30)
        if ((i % 90) == 0) tick("#1df52f", 5, i, size*0.45, size*0.40)
        else tick("#bdbdcb", 3, i,  size*0.45, size*0.43)

      // draw hands
      let t = new Date();  // get time
      tick("#61afff", 5, t.getHours() * 30, size*0.25)  // hour
      tick("#71afff", 2, t.getMinutes() * 6, size*0.35)  // min
      tick("#ee791a", 2, t.getSeconds() * 6, size*0.42)  // s

      // drwa center
      c.setFillStyle("#4d4b63"), cy, 10, { fill: true })
    setInterval(drawClock, 1000)
Enter fullscreen mode Exit fullscreen mode

This is the complete webpage to create a number of different sized clocks:

<!DOCTYPE html>
<html lang="de">

  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src=""></script>
  <script src="myclock.js"></script>

  <script>  "use strict";
    for (let i = 200; i>30; i*=0.75)
    myClock(i, "background-color: teal; margin: 10px;")

Enter fullscreen mode Exit fullscreen mode

The result should look like this:
Clock sized
You can add different styles too:

  <script>  "use strict";
    let c = ["red", "green", "blue", "yellow", "orange"]
    let k=0
    for (let i = 200; i>30; i*=0.75)
    myClock(i, "background-color: "+c[k++]+"; margin: 10px; border-radius: 25%;")
Enter fullscreen mode Exit fullscreen mode

Clocks with decorations

Making a WebComponent...

If you like the more traditional way, it is easy to convert the DML-class to act as a web-component. In fact, it is still usable in DML without changes.

You need just two small changes in the source:

a) derive the class from HTMLElement

class _myClock extends HTMLElement {....
Enter fullscreen mode Exit fullscreen mode

b) add the HTML-element-definition below the class definition

window.customElements.define('my-clock', _myClock);
Enter fullscreen mode Exit fullscreen mode

The class still works as a DML-class, but now can be used as a new html-tag too:

Enter fullscreen mode Exit fullscreen mode

The class was just quickly converted for demonstration purpose, so it might lack some functionallity. Just, it works...

Top comments (0)

Visualizing Promises and Async/Await 🤯

async await

Learn the ins and outs of Promises and Async/Await!