JavaScript finally get started, complex will not come first, today’s test, first to a system synchronization clock effect, only the simplest to obtain the system time function. Because learning needs positive feedback, otherwise it will not be effective and will inevitably lose interest in going further. At the end of my previous column “Realizing wifi Animation by using CSS3’s Animation Step property”, I made a clock. At that time, due to the blank JS, although the clock effect was finally realized, it could not synchronize with the system time. This time, to do a clock that can be completely consistent with the current time, and step by step to achieve from humble to luxurious luxuriant change.

1. Basic version, first to achieve the effect

To avoid too much interference from the complicated clock layers, we started with a very basic version, with a circle for the chassis and three straight lines for the hour, minute and second hands, well, you could call it minimalist (MUJI wind? Maybe). Since it is the basic graphics, it can be manually coded directly without the aid of Ai.

The DOM part (an 800*600 canvas, origin: (400,300))

<! -- Circular chassis -->
<circle class="base" cx="400" cy="300" r="200" /> 
<! -- Second hand of length 180 -->
<line class="pointer" id="second" x1="400" y1="300" x2="400" y2="120"/>
<! -- Minute hand of length 140 -->
<line class="pointer" id="minute" x1="400" y1="300" x2="400" y2="160"/>
<! -- hour hand of length 80 -->
<line class="pointer" id="hour" x1="400" y1="300" x2="400" y2="220"/>
Copy the code

The CSS part

<style type="text/ CSS "> /* circle */. Base {stroke:#000000; stroke-width:4; Opacity :0; fill:#FFFFFF} /* Pointer common stroke style */. Pointer {opacity:0.5; fill:none; stroke:#000000; stroke-linecap:round; stroke-linejoin:round; stroke-miterlimit:10; } / / #second{stroke-width:6; } /* < span style = "max-width: 100%; } /* hour */ #hour{stroke-width:18; } </style>Copy the code

Naturally, this final look is not so pretty, and now all the Pointers point to an initial position, which is zero.

2. Obtain the current time in the SVG graph

Until this article, I have been playing with SVG+CSS3 animations, so here is a bit more verbose. SVG, after all, is just a graphic drawing method that supports CSS control styles, but has nothing to do with the JS that controls interaction. Since JavaScript functions and operations need to be used, the first step is to make the SVG graphics created in the previous step look like ordinary pictures. The whole thing goes into the body section of the HTML file. But the big advantage of SVG over normal images here is that the tag elements can be retrieved and changed, as you can see below. In the actual application process, SVG files and JavaScript should be used in imported form. For convenience, we will not peel them out for the time being.


      
<html lang="en">
<svg>... SVG part</svg>
</html>
Copy the code

The function to get the current time is simple

<script>
var dt=new Date(a);// Get the hour
var hour=dt.getHours();
/ / to get points
var minute=dt.getMinutes();
/ / for seconds
var second=dt.getSeconds();
</script>
Copy the code

The next thing to do is to map the returned time correctly on the clock, that is, the number of degrees of rotation to the time. 360 degrees corresponds to 12 hours, 60 minutes, and 60 seconds. Accordingly, 1hour→30 degrees, 1minute→6 degrees, and 1second→6 degrees. For the convenience of use, I changed the JS above, directly changed to degree value.

// The rotation degree corresponding to the hour
var hourDeg=dt.getHours()*30;
// The number of degrees of rotation per minute
var minuteDeg=dt.getMinutes()*6;
// The number of degrees of rotation in seconds
var secondDeg=dt.getSeconds()*6;
Copy the code

CSS3 supports the basic transform:rotate property, so we define a function to add the class style to the pointer and rotate the number of degrees of the current time.

// Define a function to synchronize time
function syn(){
// Append the rotation deformation class style to the clockwise
$("hour").style.cssText="transform:rotate("+hourDeg+"deg);";
// Append the rotation deformation class style to the minute hand
$("minute").style.cssText="transform:rotate("+minuteDeg+"deg);";
// Append the rotation deformation class style to the second hand
$("second").style.cssText="transform:rotate("+secondDeg+"deg);";
}
Copy the code

Transform-origin :400px, 300px; / / Int * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

To test whether it works, I made the system time display temporarily in the window.

When this function is called, you can see that the current time corresponds exactly to the hour minute hand and second hand in the SVG graph.

3. Keep the clock ticking

In fact, after the above effect is implemented, you can lose javascript friends already know how to keep the clock running. That’s the timer function. Just set the timer to trigger once every second.

// Define a function to get the current time
function timeId(){
var dt=new Date(a);var hourDeg=dt.getHours()*30;
var minuteDeg=dt.getMinutes()*6;
var secondDeg=dt.getSeconds()*6;
$("hour").style.cssText="transform:rotate("+hourDeg+"deg);";
$("minute").style.cssText="transform:rotate("+minuteDeg+"deg);";
$("second").style.cssText="transform:rotate("+secondDeg+"deg);";
}
Call the function once before the timer starts
timeId();
// Define a timer that fires once per second
setInterval(timeId, 1000);
Copy the code

The result is an ugly clock that synchronizes with the current time. There is a slight problem, however, because the system time returned is an integer value. For a second hand, jumping one space is fine, but for a minute hand, especially an hour hand, jumping one space on the hour is obviously out of line with a real world clock. For example, 08:59:59 at 09:00:00 in the next second, the hour hand jumps from 8 to 9 sharply. Since my dial has no hands, it doesn’t seem obvious. But in the GIF you can see the minute hand jump from 42 to 43. Taking the hour hand as an example, the solution is very simple. You only need to convert the value returned by the minute into the corresponding degree of the hour hand, and add the corresponding degree of the hour hand. 60minutes→1hour→30 degrees, i.e. 1minute→0.5 degrees. Increase the hour hand by 0.5 degrees every minute. Similarly, every second, the minute hand increases by 0.1 degree. So I changed the original definition of the rotation of the hour hand and the minute hand to this

// The hour hand is corrected to increase the degree of the minute hand
var hourDeg=dt.getHours()*30 + dt.getMinutes()*0.5;
// Minute hand correction, increase the second hand corresponding to the degree
var minuteDeg=dt.getMinutes()*6+dt.getSeconds()*0.1;
Copy the code

Cut a GIF close to the hour to see the effect

base template of SVG+javascript clock

4. Discard the timer and use the animation property

The animation property of CSS3 is very powerful. Combined with the @KeyFrames animation rule definition, the rotation effect can be achieved. In the above implementation idea, since the rotation deformation is completed every second, so the animation property is not used. Let’s try to see how to achieve this effect without using timers.

First, if it is a normal rotation animation, without considering the starting position of the dynamic, the definition of the second hand animation rules and animation property method is as follows:

/* Define animation rules, rotate 360 degrees */
@keyframes second{
0%{transform:rotate(0deg)}
100%{transform:rotate(360deg)}
}
/* Define the rotation animation property of the second hand. 360 degrees takes 60 seconds */
.second{animation:second linear 60s infinite}
Copy the code

There is only one problem to solve here, which is the initial rotation Angle corresponding to 0% keyframes. After 0% confirmation, 100% only needs to increase 360 degrees. The difficulty is that javascript cannot pass in variable values to change CSS properties, but the good news is that CSS property values can be overridden by javascript. Here to achieve the idea of some trouble, I post a sentence by sentence explanation.

Second {animation: Second Linear 60s Infinite}

But the animation rule @keyframes is implemented in the following way:

  • Write the rules as content in the new style tag
  • Append the new style tag
// Create a new CSS style tag
var style = document.createElement("style");
style.type = "text/css";
// Create animation rules that accept variable parameters
// The initial keyframe is the Angle corresponding to the minute hand
// End keyframe is the Angle corresponding to the minute hand
var keyFrames = "@keyframes second {\ 0% {transform: rotate("+secondDeg+"deg); }\ 100%{transform:rotate("+(secondDeg+360) +"deg)}}";
// Write the contents of the animation rule to the newly created style tag
style.innerHTML = keyFrames;
// Append the new style tag as a child of SVG
document.getElementsByTagName("svg") [0].appendChild(style);
Copy the code

Now, just look at the second hand and see if this works. f)



The name of the animation rule
The initial degree

Create a new CSS style tag
var style = document.createElement("style");
style.type = "text/css";
// A function that defines the content of a new style tag, taking the name of the animation rule and the initial degree as parameters
function newKeyFrames(name,degree){
var keyFrames = "@keyframes "+name+" {\ 0% {transform: rotate("+degree+"deg); }\ 100%{transform:rotate("+(degree+360) +"deg)}}";
// Add a new animation rule to the new style tag
style.innerHTML += keyFrames;
}

// The animation rule name for the hour hand and the initial rotation degree are passed in as arguments
newKeyFrames("hour",hourDeg);
// The animation rule name for the minute hand and the initial rotation degree are passed in as arguments
newKeyFrames("minute",minuteDeg);
// The animation rule name for the second hand and the initial rotation degree are passed in as arguments
newKeyFrames("second",secondDeg);
// Append the style tag to the SVG element after adding all the animation rules
document.getElementsByTagName("svg") [0].appendChild(style);
Copy the code

In the CSS section, you need to add the class definition of the animation property separately.

/* It takes 60 seconds for the second hand to rotate 360 degrees */
.second{animation:second linear 60sinfinite; }/* It takes 3600 seconds for the minute hand to rotate 360 degrees
.minute{animation:minute linear 3600sinfinite; }/* It takes 216000 seconds for the clockwise to rotate 360 degrees
.hour{animation:hour linear 216000sinfinite; }Copy the code

Attach the class style to the DOM structure.

<line class="pointer second" id="second" />
<line class="pointer minute" id="minute" />
<line class="pointer hour" id="hour" />
Copy the code

So you can see what the final result is

There seems to be a bit of a problem, the second hand frame jumping effect!

Steps (60) = 60*/
.second{animation:second steps(60) 60sinfinite; }Copy the code

Perfect! Base Template of SVG+javascript+CSS3 clock

Obviously, the second approach is not as simple or even more convoluted as the first, so why is there a lot of space here exploring the feasibility of this approach? Because this case happens to be a clock, suitable for using timers, and in most cases, we need a way to solve the problem with acceptable variables as parameters of animation rules, so.

Above is the skeleton, below is the soul

The hard part is done, now that the animation is out, it’s time to do some gorgeous effects based on this template. (I suggest you modify the source code based on the following dynamic effects, with detailed comments, can be directly replaced with layer elements) which template to modify based on? It’s a matter of personal preference, because this timer is single-threaded and does not eat memory, so in this case, it’s temporarily replaced with this template.


      
<! -- Important note: !!!! Before exporting Ai, make sure that all Pointers are placed at the initial zero position -->
<html lang="en">
<svg>
<style type="text/css">
/* The style generated when the Ai is exported needs to be replaced with */ each time it is used
.st0{}.../* The value of the rotation origin is redefined according to the needs of different base maps */
.pointer{transform-origin:}</style>
<! When sorting layers, follow the base image - hour hand - minute hand - second hand - overlay (if any) ->
<g id="base">Path corresponding to the base diagram</g>
<g class="pointer" id="hour">The path of the hour hand</g>
<g  class="pointer" id="minute">Path of the minute hand</g>
<g class="pointer" id="second">The path corresponding to the second hand</g>
<g id="overlay">Path of overlay</g>
</svg>
<script>
// Since jQuery is not used, a basic function is encapsulated
    function $(id){
    var idValue=document.getElementById(id);
    return idValue;
}
</script>
<script>
// Define a function that gets the current time converted to the rotation deformation Angle
function timeId(){
var dt=new Date(a);// The hour hand is corrected to increase the degree of the minute hand
var hourDeg=dt.getHours()*30 + dt.getMinutes()*0.5;
// Minute hand correction, increase the second hand corresponding to the degree
var minuteDeg=dt.getMinutes()*6+dt.getSeconds()*0.1;
var secondDeg=dt.getSeconds()*6;
// Append the rotation deformation style to the clockwise
$("hour").style.cssText="transform:rotate("+hourDeg+"deg);";
// Append the rotation deformation style to the minute hand
$("minute").style.cssText="transform:rotate("+minuteDeg+"deg);";
// Append the rotation deformation style to the second hand
$("second").style.cssText="transform:rotate("+secondDeg+"deg);";
}
// Execute the function once before the timer triggers
timeId();
// set the timer to be triggered every 1000ms
setInterval(timeId, 1000);
</script>
</html>
Copy the code

Like clock? ok! Like this simple wind codepen link with no scale

Below are a variety of boring show series, too lazy to see can directly skip, just as well.

Bare chassis too monotonous? How about a simple scale? Codepen link

Go to the trouble of full digital scale Codepen links

Like watches, said to change on the change, is not the replacement of things

Too cliche? See if this iWatch style is your thing

All right, no more fun. It’s the same thing. Fast Chinese New Year, the last to a combination of Chinese and foreign, lucky cat with gold and jade full of golden big fu clock. (I know it is the year of the Pig, but lucky pig, that pig hoof swing too funny, so) about the lucky cat claw swing back and forth can refer to my previous column, “no three-dimensional, no animation, CSS3 3D animation properties introduction” is a very basic 3D properties. It’s just that it’s flat, so the arm moves a little weird.

I wish you good luck in the New Year, even if the Internet winter cold, but also to smile. Sauce.