Beautiful Object Oriented Clock...
Eckehard
Posted on July 26, 2021
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"
unselectBase()
// 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() {
c.clear()
// 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")
c.circle(cx, cy, 10, { fill: true })
}
drawClock()
setInterval(drawClock, 1000)
}
}
This is the complete webpage to create a number of different sized clocks:
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>title</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://efpage.de/DML/DML_homepage/lib/DML-min.js"></script>
<script src="myclock.js"></script>
</head>
<body>
<script> "use strict";
for (let i = 200; i>30; i*=0.75)
myClock(i, "background-color: teal; margin: 10px;")
</script>
</body>
</html>
The result should look like this:
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%;")
</script>
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 {....
b) add the HTML-element-definition below the class definition
window.customElements.define('my-clock', _myClock);
The class still works as a DML-class, but now can be used as a new html-tag too:
<body>
<my-clock></my-clock>
</body>
The class was just quickly converted for demonstration purpose, so it might lack some functionallity. Just, it works...
Posted on July 26, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.