# A Digital-Analog Clock🕰 : Day 2 #JavaScript30


👋  Hello people!

The title might sound like an oxymoron, but the blog is going to be quite clear. In this blog, we will be making a JavaScript Analog Clock. As its done digitally, I called it a Digital Analog Clock. To the end, we will be building a functional Clock that can be used on any webpage. Check the [live demo](https://srivenkat13.github.io/JS30/02-Digital-Analog-clock/index.html) and without wasting much "time" let's get started.


The starter files for this project can be found [here](https://github.com/srivenkat13/JS30/tree/master/02-Digital-Analog-clock).


## 🧠 HTML && CSS
The HTML for this project is nothing more than 7 lines. All we have is a `div` for `clock-face` and three nested `div`s inside for the hands of the clock. All three hands have a `hand` class in common and `second-hand`, `min-hand` and `hour-hand` respectively for each clock hand.

In CSS we have styling applied for `.hand` class. We need to add few more rules to make it work. For a clock to function we should be have moving hands. We shall use `transform:rotate()` property to achieve this. First let's try it out on seconds hand, apply this styling.
```css
.second-hand{
    transform:rotate(30deg)
}
```
Well that should result something like below and its weird. We want our clock hands to rotate along its center not anywhere else.

![clock.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1614169673982/AyJbip1BD.png)

For that we need to transform the origin to the right most of the element. Along with that lets add a `transition` for smooth movement of clock hands.
```css
.hand{
    transform-origin : 100%
    /* by default its 50%, making it 100 moves it to right */
    transition: all 0.05s ease-in-out;

}
```
Everything is fine, but the clock hands are pointing in the wrong direction ( left ). They should be facing north, this is important. `transform: rotate(90deg);` in `.hand` class should fix this. Remember, this `90deg` shift is compensated later.
That's pretty much the HTML and Styling part of it.

## 🚴  Approach 
Before heading to JS, let's see how we are going to implement this. Our clock needs to display the exact time of the internet clock. For that, we grab the `date` object in a variable from which we can get seconds, minutes and hours. Once these values are obtained they should be converted to degrees, so that we can `transform:rotate()` clock hands by that amount of degrees. 

## 💛 JavaScript
To start with, we `querySelect` three classes `.second-hand`, `.min-hand` and `.hour-hand` in to individual variables.
``` javascript
const secondHand = document.querySelector('.second-hand')
const minuteHand = document.querySelector('.min-hand')
const hourHand = document.querySelector('.hour-hand')
```
Next, declare a function `setDate()` , grab the date object as said before. But we don't  need  complete date object, it has lot of information. All we want is seconds , minutes and hours values.
``` javascript
function setDate() {
    const now = new Date();

    const seconds = now.getSeconds();

    const minutes = now.getMinutes();
    
    const hours = now.getHours();
}
```
Now, we convert this `seconds` into degrees, as the `transform:rotate(_deg)` accepts only degrees. For each second we update the `.second-hand` class with the new degree calculated. 
Let's see how to do this for seconds and its quite similar for minutes and hours hands too. 
As the second hand moves `60` positions to complete  one revolution  we get, `secondsDegrees = ((seconds / 60) * 360) `. This calculation will lag by 90 degrees. If you remember in CSS we have added a style to rotate all hands by `90deg`, that should be added here as well. The obtained degrees value should be updated with the `.second-hand`. This operation needs to happen every second. We use `setInterval` function to achieve that.

``` javascript
function setDate() {
    const now = new Date();

    const seconds = now.getSeconds();
    const secondsDegrees = ((seconds / 60) * 360) + 90;
    secondHand.style.transform = `rotate(${secondsDegrees}deg)`;
}
setInterval( setDate,1000)
// the second argument expects time in milliseconds.
``` 
We are almost to the end. These steps have to be performed for minutes and hours hands as well. Hours hand has `12` positions, values vary a bit over there. To the end, the function looks like below.
```javascript
function setDate() {
    const now = new Date();

    const seconds = now.getSeconds();
    const secondsDegrees = ((seconds / 60) * 360) + 90;
    secondHand.style.transform = `rotate(${secondsDegrees}deg)`;

    const minutes = now.getMinutes();
    const minutesDegrees = (( minutes / 60)*360) + 90;
    minuteHand.style.transform = `rotate(${minutesDegrees}deg)`;
    
    const hours = now.getHours();
    const hoursDegrees = ((hours/12)*360)+ 90;
    hourHand.style.transform = `rotate(${hoursDegrees}deg)`;
}
setInterval(setDate, 1000)
```

If everything is done well, your clock should be ticking by now. If it doesn't, not to worry, *even the dead clock is right twice a day*. Just kidding it should work fine.

## Limitations of this clock
You might have observed some, issues by now. If not let me list them.
- The minutes & hours hand sticks to its position till the next updated value arrives. What do I mean by this? In a real clock, all three clocks move every second. The movement in minutes and hours hand is so subtle that we don't notice it. This clock fails to do it.
- The second's hand refreshes when it reaches 60 seconds mark, which makes a  little weird animation. 
- The clock tries to catch up when moving to another tab in the browser and coming back. This is because the Browser tries to throttle Javascript when you're not actively viewing that tab.
  
  The first two issues can be fixed and I have made  [another clock ](https://srivenkat13.github.io/AnalogClock/) earlier addressing both of them. It can be found [here](https://github.com/srivenkat13/AnalogClock) the script.js is very well documented, it's easy to understand. 

## 🤝Thank you for reading till the end.
That's all for today. Feel free to drop a comment, if anything can be done better or any more features can be added. 
See you in my next blog. Until then,

_Bye !_

## References
[*The course*](https://javascript30.com/), *from which the project is picked.*

[*MDN: Date object*](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date)

[*MDN: setInterval*](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval)
