I’m participating in nuggets Creators Camp # 4, click here to learn more and learn together!

Ihope_top.gize. IO /my-demo/dem…

This article has been published to the public account: Baili Qingshan

preface

A few days ago, I found a small case I learned when I started to learn the front end. I use CSS to draw a rotating dial. I don’t know if everyone has written it, as shown in the picture below

Share this little case for you today, and the effect of the original case is completely implemented with CSS, because the clock rotation have rules to follow, just set a timing animation, I in order to simplify the code, and can get the current time, so use js optimization, because the case is very small, so I don’t have frame, the original start directly, Since this simple article is aimed at beginners, it will be explained in more detail

The development of

Initialize the

The first step is to find a folder, create index.html, then introduce a style. CSS and initialize some styles

The dial to make

Now let’s make the dial

panel

The first part is the panel. We only use one node for the HTML part of the panel, and use CSS for the rest

  <div id="watch">
    <! - dial - >
    <div class="frame-face"></div>
  </div>
Copy the code

First we give the dial a basic style to determine the basic structure, then add some gradients and shadows to create a little bit of stereo

#watch .frame-face {
  position: relative;
  width: 30em;
  height: 30em;
  margin: 2em auto;
  border-radius: 15em;
  background: -webkit-linear-gradient(top, #f9f9f9.# 666);
  background: -moz-linear-gradient(top, #f9f9f9.# 666);
  background: linear-gradient(top, #f9f9f9.# 666);
  box-shadow: 0.5 em 0.5 em 4em rgba(0.0.0.0.8);
}
Copy the code

Then we used pseudo-class elements to draw a radial gradient to create a sense of hierarchy and make the dial more three-dimensional

#watch .frame-face:before {
  content: ' ';
  width: 29.4 em;
  height: 29.4 em;
  border-radius: 14.7 em;
  position: absolute;
  top:.3em;
  left:.3em;
  background: -webkit-radial-gradient(ellipse at center, rgba(246.248.249.1) 0%.rgba(229.235.238.1) 65%.rgba(205.212.217.1) 66%.rgba(245.247.249.1) 100%);
  background: -moz-radial-gradient(ellipse at center, rgba(246.248.249.1) 0%.rgba(229.235.238.1) 65%.rgba(205.212.217.1) 66%.rgba(245.247.249.1) 100%);
  background: radial-gradient(ellipse at center, rgba(246.248.249.1) 0%.rgba(229.235.238.1) 65%.rgba(205.212.217.1) 66%.rgba(245.247.249.1) 100%);
}
Copy the code

This still doesn’t look good, so let’s add a pseudo-class to make the main panel of the dials look more realistic through the contrast effects of shadows and gradients

#watch .frame-face:after {
  content: ' ';
  width: 28em;
  height: 28em;
  border-radius: 14.2 em;
  position: absolute;
  top:.9em;
  left:.9em;
  box-shadow: inset rgba(0.0.0.2).2em .2em 1em;
  border:.1em solid rgba(0.0.0.2);
  background: -webkit-linear-gradient(top, #fff.#ccc);
  background: -moz-linear-gradient(top, #fff.#ccc);
  background: linear-gradient(top, #fff.#ccc);
}
Copy the code

calibration

There are small scale points around the dial, so that we can know the specific time, here we set 60 scale points for the dial, dom node we first write a scale point container, because there are too many scale points, we will use JS generation later

    <! - scale - >
    <ul id="minute-marks"></ul>
Copy the code

Let’s do a basic style

#minute-marks li {
  display: block;
  width: 0.2 em;
  height: 0.6 em;
  background: # 929394;
  position: absolute;
  top: 50%;
  left: 50%;
  margin: -0.4 em 0 0 -0.1 em;
}
Copy the code

Here, we adjust the position of each scale point by transform to achieve the corresponding effect. The scale of the hour point is more prominent than the others, so we need to find the scale of the hour point and add a prominent effect to it

window.onload = function () {
  // Generates a scale
  let markWrap = document.getElementById('minute-marks')

  for (let index = 0; index < 60; index++) {
    let markItem = document.createElement('li')
    markItem.style.cssText = "transform:rotate(" + index * 6 + "Deg) translateY em (12.7)";
    if (index % 5= =0) {
      markItem.style.width = "0.3 em";
      markItem.style.height = "1em";
    }
    markWrap.appendChild(markItem)
  }
}
Copy the code

Here we can also consider adding some graduated digital marks

<ul id="digits">
  <li>3</li>
  <li>6</li>
  <li>9</li>
  <li>12</li>
</ul>
Copy the code
#digits {
    width: 30em;
    height: 30em;
    border-radius: 15em;
    position: absolute;
    top: 0;
    left: 50%;
    margin-left: -15em;
}
#digits li {
  font-size: 1.6 em;
  display: block;
  width: 1.6 em;
  height: 1.6 em;
  position: absolute;
  top: 50%;
  left: 50%;
  line-height: 1.6 em;
  text-align: center;
  margin: -.8em 0 0 -.8em;
  font-weight: bold;
}

#digits li:nth-child(1) {
  transform: translate(7em.0)}#digits li:nth-child(2) {
  transform: translate(0.7em)}#digits li:nth-child(3) {
  transform: translate(-7em.0)}#digits li:nth-child(4) {
  transform: translate(0, -7em)}Copy the code

Here we will directly add the center point of the axis where the pointer rotates

#digits:before {
  content:' ';
  width:1.6 em;
  height:1.6 em;
  border-radius:.8em;
  position:absolute;
  top:50%; left:50%;
  margin: -.8em 0 0 -.8em;
  background:# 121314;
}
#digits:after {
  content:' ';
  width:4em;
  height:4em;
  border-radius:2.2 em;
  position:absolute;
  top:50%; left:50%;
  margin: -2.1 em 0 0 -2.1 em;
  border:.1em solid #c6c6c6;
  background:-webkit-radial-gradient(ellipse at center, rgba(200.200.200.0), rgba(190.190.190.1) 90%.rgba(130.130.130.1) 100%);
  background:-moz-radial-gradient(ellipse at center, rgba(200.200.200.0), rgba(190.190.190.1) 90%.rgba(130.130.130.1) 100%);
  background:radial-gradient(ellipse at center, rgba(200.200.200.0), rgba(190.190.190.1) 90%.rgba(130.130.130.1) 100%);
}
Copy the code

Pointer to the development

Next we carry on the development of dial pointer

Here we prepare three DOM, namely hour hand, minute hand and second hand

    <! - pointer -- -- >
    <div class="hours-hand"></div>
    <div class="minutes-hand"></div>
    <div class="seconds-hand"></div>
Copy the code

In the same development

The main part of the hour hand is divided into a pin and a tip. The pin has a rectangle, and the tip can be composed of a semicircle and a triangle

#watch .hours-hand {
    width:.8em;
    height:7em;
    border-radius:0 0 .9em .9em;
    background:# 232425;
    position:absolute;
    bottom:50%; left:50%;
    margin:0 0 -.8em -.4em;
    box-shadow:# 232425 0 0 2px;
    transform-origin:0.4 em 6.2 em;
    transform:rotate(-25deg);
}
#watch .hours-hand:before {
    content:' ';
    background:inherit;
    width:1.8 em;
    height:.8em;
    border-radius:0 0 .8em .8em;
    box-shadow:# 232425 0 0 1px;
    position:absolute;
    top: -.7em; left: -.5em;
}
#watch .hours-hand:after {
    content:' ';
    width:0; height:0;
    border:.9em solid # 232425;
    border-width:0 .9em 2.4 em .9em;
    border-left-color:transparent;
    border-right-color:transparent;
    position:absolute;
    top: -3.1 em; left: -.5em;
}
Copy the code

Note that the transform-origin property is used to set the rotate reference point for the dom. The dom will rotate at this point, or at its own center if not

Minute hand development

To make a distinction, let’s give a different style for each pointer, a rectangle for the minute hand

#watch .minutes-hand {
    width:.8em;
    height:12.5 em;
    border-radius:.5em;
    background:# 343536;
    position:absolute;
    bottom:50%; left:50%;
    margin:0 0 -1.5 em -.4em;
    box-shadow:# 343536 0 0 2px;
    transform-origin:0.4 em 11em;
}
Copy the code

The second hand development

The second hand is made up of three parts, a rounded rectangle at the tail, a circle that overlaps the center point, and a long tip, which can also be made with rounded corners

/ * the second hand * /
#watch .seconds-hand {
  width:.2em;
  height:14em;
  border-radius:.1em .1em 0 0/10em 10em 0 0;
  background:#c00;
  position:absolute;
  bottom:50%; left:50%;
  margin:0 0 -2em -.1em;
  box-shadow:rgba(0.0.0.8) 0 0 .2em;
  transform-origin:0.1 em 12em;
}
#watch .seconds-hand:after {
  content:' ';
  width:1.4 em;
  height:1.4 em;
  border-radius:.7em;
  background:inherit;
  position:absolute;
  left: -.65em; bottom:1.35 em;
}
#watch .seconds-hand:before {
  content:' ';
  width:.8em;
  height:3em;
  border-radius:.2em .2em .4em .4em/.2em .2em 2em 2em;
  box-shadow:rgba(0.0.0.8) 0 0 .2em;
  background:inherit;
  position:absolute;
  left: -.35em; bottom: -3em;
}
Copy the code

Let the needle spin

We have developed the basic styles of the dial and pointer, and now we are going to let the needle rotate. When we write CSS, we already know that the position of the pointer is rotated by a certain Angle by the transform, so we need to move the pointer regularly by changing the Angle

  setInterval(function () {
    var time = new Date(a);var hour = time.getHours()
    var minute = time.getMinutes();
    var second = time.getSeconds();
    var hournum;
    if (hour > 12) {
      hournum = ((hour - 12) + minute / 60) * 30;
    } else {
      hournum = (hour + minute / 60 * 100) * 30;
    }
    var minnum = (minute + second / 60) * 6 + second / 60;
    var sennum = second * 6;
    document.getElementsByClassName("hours-hand") [0].style.transform = "rotate(" + hournum + "deg)"
    document.getElementsByClassName("minutes-hand") [0].style.transform = "rotate(" + minnum + "deg)"
    document.getElementsByClassName("seconds-hand") [0].style.transform = "rotate(" + sennum + "deg)"
  }, 1000);
Copy the code

And you’re done

Digital table development

The hands are also very intuitive, but they are always not as intuitive and accurate as the numbers, so we can add a digital dial. Digital dial is more simple, we get the current minute seconds, regular refresh is good, here needs the host column dial on the level, can not cover the pointer

    <! -- Digital dial -->
    <div class="digital-wrap">
      <ul class="digit-hours"></ul>
      <ul class="digit-minutes"></ul>
      <ul class="digit-seconds"></ul>
    </div>
Copy the code
#watch .digital-wrap {
  width:9em;
  height:3em;
  border:.1em solid # 222;
  border-radius:.2em;
  position:absolute;
  top:50%; left:50%;
  margin:3em 0 0 -4.5 em;
  overflow:hidden;
  background:#4c4c4c;
  background:-webkit-linear-gradient(top, #4c4c4c.#0f0f0f);
  background:-moz-linear-gradient(top, #4c4c4c.#0f0f0f);
  background:-ms-linear-gradient(top, #4c4c4c.#0f0f0f);
  background:-o-linear-gradient(top, #4c4c4c.#0f0f0f);
  background:linear-gradient(to bottom, #4c4c4c.#0f0f0f);
}
#watch .digital-wrap ul {
  float:left;
  width:2.9 em;
  height:3em;
  border-right:.1em solid # 000;
  color:#ddd;
  font-family:Consolas, monaco, monospace;
  text-align: center;
  line-height: 3em;
}
#watch .digital-wrap ul:last-child {width: 3em; border:none }
Copy the code
// attach the pointer above to rotate js
if(hour<10){
    hour="0"+parseInt(hour);
}
if(minute<10){
    minute="0"+parseInt(minute);
}
if(second<10){
    second="0"+parseInt(second);
}
document.getElementsByClassName("digit-hours") [0].innerHTML=hour;
document.getElementsByClassName("digit-minutes") [0].innerHTML=minute;
document.getElementsByClassName("digit-seconds") [0].innerHTML=second;
Copy the code

And you’re done.