Creating a sleek animated analog clock using CSS and jQuery

I am facing a small issue with my CSS3/jQuery analog clock.

Currently, the movement of the clock hands is a bit abrupt. I would like the animation to be smooth. I attempted using transition: all .1s, but it gets messy when the clock hands reach the top position.

The hands of the clock are being rotated using transform: rotate(). Each movement rotates them by 6 degrees.

A potential solution could involve changing the rotation angles to make the animation smoother. Instead of rotating each hand by 6 degrees every second, minute, or hour, consider rotating by 1 degree for every 1/6th of a second for the second-hand, every 10 seconds for the minute-hand, and every 10 minutes for the hour-hand. This adjustment might create a more seamless animation effect, although the implementation details are not clear to me.

This is the JavaScript code snippet:

$(function() {

      setInterval( function() {
      var seconds = new Date().getSeconds();
      var sdegree = seconds * 6;
      var srotate = "rotate(" + sdegree + "deg)";

      $("#sec").css({ "transform": srotate });

      }, 1000 );

      setInterval( function() {
      var hours = new Date().getHours();
      var mins = new Date().getMinutes();
      var hdegree = hours * 30 + (mins / 2);
      var hrotate = "rotate(" + hdegree + "deg)";

      $("#hour").css({ "transform": hrotate});

      }, 1000 );

      setInterval( function() {
      var mins = new Date().getMinutes();
      var mdegree = mins * 6;
      var mrotate = "rotate(" + mdegree + "deg)";

      $("#min").css({"transform" : mrotate });

      }, 1000 );

});

Check out the jsFiddle Demo here

If you understand the problem and have any insights, I would greatly appreciate your help :)

Answer №1

Establish a linear transition for the clock hands:

#clock div {
    -moz-transition: all 1s linear;
    -webkit-transition: all 1s linear;
    -o-transition: all 1s linear;
    transition: all 1s linear;
}

To prevent the abnormal occurrence where the hands reverse to reach zero, it is recommended to adjust your JavaScript code to operate in milliseconds. This way, the rotation value (in degrees) will only increase. CSS rotation can smoothly accommodate this change:

$(function() { 
     var i=0;
    setInterval( function() {
        //obtain time elapsed since midnight in milliseconds
         var now = new Date(),
        then = new Date(
        now.getFullYear(),
        now.getMonth(),
        now.getDate(),
        0,0,0),
        mil = now.getTime() - then.getTime(); // difference in milliseconds

          var h = (mil/(1000*60*60));
          var m = (h*60);
          var s = (m*60);
          //console.log(h+":"+m+":"+s);   

      var sdegree = (s * 6);
      var srotate = "rotate(" + sdegree + "deg)";  
      $("#sec").css({ "transform": srotate });

      var hdegree = h * 30 + (h / 2);
      var hrotate = "rotate(" + hdegree + "deg)";
      $("#hour").css({ "transform": hrotate});

      var mdegree = m * 6;
      var mrotate = "rotate(" + mdegree + "deg)";      
      $("#min").css({ "transform" : mrotate });

         if(i>0){
             $("#clock").addClass("transform");       
         }
         i++;

      }, 1000 );

});

http://jsfiddle.net/FHNJf/10/

UPDATE:

A pure JS method for achieving smooth sweeping hands has been provided here. It utilizes requestAnimationFrame to regulate the loop timings. As it does not rely on CSS transitions, it avoids the odd behavior of hands 'catching up' when returning focus to the browser tab.

//use requestAnimationFrame for smoothness (shimmed with setTimeout fallback)
window.requestAnimFrame = (function(){
  return  window.requestAnimationFrame       ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame    ||
          function( callback ){
              window.setTimeout(callback, 1000 / 60);
          };
})();

//initialize the clock in a self-invoking function
(function clock(){ 
    var hour = document.getElementById("hour"),
        min = document.getElementById("min"),
        sec = document.getElementById("sec");
    //set up a loop
    (function loop(){
        requestAnimFrame(loop);
        draw();
    })();
    //position the hands
    function draw(){
        var now = new Date(),//now
            then = new Date(now.getFullYear(),now.getMonth(),now.getDate(),0,0,0),//midnight
            diffInMil = (now.getTime() - then.getTime()),// difference in milliseconds
            h = (diffInMil/(1000*60*60)),//hours
            m = (h*60),//minutes
            s = (m*60);//seconds
        //rotate the hands accordingly
        sec.style.webkitTransform = "rotate(" + (s * 6) + "deg)";
        hour.style.webkitTransform = "rotate(" + (h * 30 + (h / 2)) + "deg)";
        min.style.webkitTransform = "rotate(" + (m * 6) + "deg)";
    } 
})();

http://jsfiddle.net/FHNJf/13/

Answer №2

To make the transition smoother for hand elements, you can set the transition duration. Here's an example of how to do it:

#clock div {
    -webkit-transition-duration: 1.0s;
    -moz-transition-duration: 1.0s;
    -o-transition-duration: 1.0s;
    transition-duration: 1.0s;
}

Check out the updated fiddle here

Answer №3

If you want the movement of the second hand (and all other hands) to be seamless, consider applying the following CSS to the #sec div:

[prefix-]transition: all 1.00s linear 0.0s;

However, this solution may only solve part of the problem. You will need to carefully handle the transform for rotation to avoid any issues near the 12 o'clock position.

Alternatively, you could use a single setInterval(...) function that creates a new Date() object and updates the clock hands accordingly.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How to toggle between displaying divs using JavaScript and Jquery

How can I use JavaScript to show or hide specific divs on page load and upon clicking different links? I want to display the "houseImages" div by default, while hiding the "landImages", "renovationImages", "UpcomingImages", and "voteForNext" divs. Then, w ...

"In strict mode, the object is subjected to specific rules

I am facing a challenge with an object in my project that needs to run the content of the page within strict mode. Even after attempting to return it for global scope usage, I still haven't been able to resolve the issue. (function($) { "use stric ...

How can you retrieve the index of the outer repeater item within nested ng-repeaters in AngularJS?

If I have multiple ng-repeat loops nested within each other like in the following example: <div ng-repeat="outeritem in outerobject"> <div ng-repeat="inneritem in innerobject" ng-click="function(inneritem.key, $index)"></div> <d ...

Creating a series of promises in a structured chain

How can the code structure be improved, especially regarding exception handling within a "promise chain"? $("#save").click(function(e) { e.preventDefault(); let $self = $(this); let profile = {} $self.prop("disabled" ...

Utilizing long polling technique with jQuery/AJAX on the server end

Currently, I am facing an issue with long polling on a single page that contains multiple pages. The problem arises when a new request is made while a previous request is still processing. Even though I attempt to abort the previous request, it completes b ...

Can WikiData be accessed by providing a random pageId?

My current project involves creating a Wikipedia Search App with a 'Feel Lucky' button. I have been trying to figure out if it's possible to send a request for Wikidata using a specific pageid, similar to the code below: async function lucky ...

Positioning the bottom of a two-column layout using CSS

I am working on a 2 column layout that should have a height of 100% of the window size. The left side will contain an image taking up 90% of the window size positioned at the bottom of the wrapper. On the right side, there will be text occupying the top 50 ...

"Viewed By" aspect of Facebook communities

I'm working on implementing a feature that shows when a post has been seen, similar to Facebook groups, using JS and PHP. I've been able to track the number of times a post has been seen through scrolling actions, but now I want to determine if u ...

Creating a universal representation of the global object in JavaScript that is not tied to any specific implementation

Looking to define the global object in JavaScript with just one line of code: var global = this.global || this; This statement is within the global scope, meaning that in browsers, the this keyword refers to the window object. If this is the first line o ...

Sending a collection of items to a web API endpoint

Hey there, I'm having an issue with posting a list of objects to a web API method using the following code snippet: var uri = "http://localhost:" + port + "/api/Account"; $.ajax({ dateType: "json", method: "POST", url: uri, da ...

Traverse an array containing nested objects using Javascript

I am facing difficulty printing out objects stored in an array. When I console log, this is the result: console.log(product.categories) https://i.stack.imgur.com/YVprQ.png How can I iterate through these nested objects to display them individually like t ...

The problem of undefined icons in Material UI's Stepper StepLabel

Having some trouble incorporating a custom Step Label Icon within the nodes of the Stepper Component provided by Material UI. I want to add an icon to each circle, similar to what is shown in this Material UI demo: https://i.sstatic.net/WLOcS.png However, ...

What is the most effective method for customizing non-MUI elements within an MUI framework?

As someone new to React and development in general, I understand that there are various ways to style elements within React itself: importing CSS, using locally scoped CSS modules, implementing CSS-in-JS via libraries like Styled Components or Emotion, ut ...

What is the process for adding an image to a scene using menu options?

I'm looking for assistance in loading an image into a scene upon clicking a menu option. Any guidance would be greatly appreciated. Please let me know if more information is required. Here's the method I've tried, which involves testing a v ...

The MessageError: expressjs is unable to read the property "image" because it is null

I am currently working on developing a shopping cart using express and mongodb. However, I encountered an error when attempting to include an image category in the form. Here is the code snippet for handling post requests in admin_product.js: router.post(& ...

Efficiently managing modules with requirejs and Backbone.Marionette

After organizing the file structure of my web app, utilizing RequireJs and Backbone.Marionette, it now looks like this: |- main.js |- app.js |- /subapp1 |- subapp1.js |- subapp1.router.js |- /subapp2 |- subapp2.js | ...

Adjust the text to fit neatly within a circular-shaped column container

I am currently working with Bootstrap 5 and I have a row with two columns positioned next to each other. My goal is to apply rounded borders to the left column while ensuring that the content remains within the div. Below is the code snippet: <div clas ...

When using Node.js, Express.js, and MongoDB, ensure that the route.post() function is provided with proper callback functions instead of

I've been working on setting up a MEAN (MongoDB, Express, Node.js, Angular 6) application. I'm trying to post user signup form data to a MongoDB database, but I keep getting an error message. This is my first time working with the MEAN stack and ...

Why is npm attempting to compile a previous version of my code?

Being a complete newbie to npm and node.js, I hope you can bear with me if I'm lacking in providing the right details. I am working on developing a plugin for a website that utilizes an out-of-the-box framework within npm. Initially, everything was ru ...

Using identical class names in different components was not possible as the CSS was not being contained within the styled component's scope

I am encountering a frustrating issue that seems to defy the essence of CSS in JS. The problem arises when I use styled-components and attempt to apply a classname that is already used higher up in the React component tree within a styled component. Surpri ...