Ensure that CSS transformation rotation always moves in a clockwise direction without surpassing 360 degrees

As I work on designing a clock, I have implemented a combination of JS and CSS to create a seamless animation for the clock's "hands." This involves converting seconds, minutes, and hours into their corresponding degrees in the analog clock:

function clock() { 
  var t = moment(),
      s = t.seconds() * 6,
      a = t.minutes() * 6,
      o = t.hours() % 12 / 12 * 360 + (a / 12);

  $(".hour").css("transform", "rotate(" + o + "deg)");
  $(".minute").css("transform", "rotate(" + a + "deg)");
  $(".second").css("transform", "rotate(" + s + "deg)");
}

setInterval(clock, 1000);

One issue I encountered is that after reaching 360 degrees, I don't want the variable to continue increasing indefinitely. Instead, I prefer it to return to 0 and start over. However, CSS causes the hands to rotate anticlockwise, creating an unwanted effect.

Here's an example.

I've contemplated removing the transition property using JS when transitioning from 360 back to 0, and then reapplying it. While this could be a solution, I'm curious if there might be a cleaner approach.

Answer №1

To achieve this effect, you cannot do it using native methods. When transitioning from 356 degrees to 2 degrees, the rotation will always be counter clockwise. If you are okay with a visible tick when transitioning between these angles, you can simply remove the transition. However, there is no real reason to do so. Instead, try utilizing the fact that the `rotate` property can accept values above 360 degrees. So, rather than resetting back to 0, allow the clock to continue increasing endlessly (keep in mind that the highest integer value in JavaScript is 9007199254740991, so you may need to refresh your browser after a few million years... :)).

You can keep track of rotations by creating a separate object named `counter` outside of the setInterval callback like shown below:

var counter = {
  s: 0,
  a: 0,
  o: 0
};

var previous = null;

Next, you'll want to store all values from the previous iteration and compare them to the current values. If needed, increment the respective counter by one.

if(previous){
  if(s < previous.s){
    counter.s += 1;
  }
  if(a < previous.a){
    counter.a += 1;
  }
  if(o < previous.o){
    counter.o += 1;
  }
}

previous = {
  s: s,
  a: a,
  o: o
};

Finally, set the multiplied degree value in your inline CSS. This method allows you to maintain access to the actual values of `s`, etc. if needed for any other purpose.

$(".second").css("transform", "rotate(" + (s + 360 * counter.s) + "deg)");

For a working example, check out this fiddle: https://jsfiddle.net/dannyjolie/tccroo1q/6/

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

Is it best practice to display a DIV once it is no longer visible after scrolling down?

Upon opening my website, an information box (div) appears on the screen. However, when the user scrolls down and the box is no longer visible, I want it to always appear in the top right corner while scrolling. I have figured out how to keep it visible at ...

What steps can I take to ensure the proper formatting of the `select` input on Mac OS?

How can I maintain consistent formatting for my form across different operating systems? Currently, the form looks good on Windows, but I want to ensure that the select input appears consistently on Mac OS, iOS, and Android devices as well. The image bel ...

Please call hooks exclusively within the body of a function component. (fb.me/react-invalid-hook-call)

import { useEffect } from "react"; export const Routes = () => { useEffect(() => { console.log("red") }, []); const a = [{ name: "sathish" }]; const b = [{ name: "pandi" }]; const c = [{ name: ...

Converting the AppDelegate.m file to AppDelegate.mm and updating the AppDelegate.h file during the transition from React Native 0.66.4 to 0.71.3

Original code in AppDelegate.h: #import <React/RCTBridgeDelegate.h> #import <UIKit/UIKit.h> #import <UserNotifications/UserNotifications.h> @interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate, UNUserNotificat ...

Turn off the footer button on materialize.css modal

I'm struggling to disable one of the modal footer buttons in materialize.css. I tried using disabled="disabled", but it doesn't seem to be working. You can see my example on jsfiddle. <a class="waves-effect waves-light btn modal-trigger" href ...

Navigating through asynchronous functions without the use of promises

After delving into web-app development using angularJS with its promise library, I find myself facing a new project that lacks such a feature. How can I tackle this challenge without importing an external promise library? To simplify the situation, I need ...

Tips for managing and showcasing various user inputs in an array using JavaScript

I have been tasked with storing multiple user input values in a JavaScript array using the push method. Below is the code: <body> <h3>employee form</h3> <div class="row"> <div class="col-md-6" ...

Sorting tables using jQuery and fixing CSS issues specifically for Internet Explorer 8

I'm currently working on making sure this page is compatible with IE 8. The jquery code that's being used allows for classes to be assigned based on odd and even elements, but it doesn't seem to function properly on IE 8. You can check out ...

Maintaining an array of data in Cordova/Phonegap that persists when the app is closed and reloads when reopened

I have set up an array in my application that looks like this [{pseudo: "test", id: 0}, {pseudo: "Lucia", id: 2}] Is there a way to preserve this array even when the app is closed? Additionally, I would like to access the array directly upon reopening th ...

Executing a sequence of two asynchronous calls in a serial manner using the promise API

I recently posted a question on Stack Overflow that was somewhat similar to this, but the current issue requires chaining the requests serially. I have two asynchronous requests where the second request depends on the result of the first request in order t ...

Saving a picture from browser cache to the server

Following the guidance provided in this thread Preview an image before it is uploaded, I was able to implement a feature on my website that allows users to preview images before submitting them. I currently have code set up to display the image preview on ...

Issues arising with data transmission through the use of AJAX and the POST method

I am facing an issue while trying to implement AJAX with the POST method. Initially, everything was working fine with the GET method. However, upon changing the method to POST, I noticed that the server is receiving null data. I'm puzzled by this situ ...

What is the best way to display the Edit and Delete buttons in a single column?

Currently, I am encountering a small issue. I am trying to display Edit and Delete Buttons in the same column but unfortunately, I am unable to achieve that. Let me provide you with my code. var dataTable; $(document).ready(function () { dataTa ...

Intersecting object identification, fresh Function

I'm currently utilizing the "Sinova / Collisions" library on GitHub along with Node.js. The library can be found at https://github.com/Sinova/Collisions. I am in need of a function that allows me to delete all data at once, as the current function for ...

When using the updateMany function, only update the field if it already exists, without creating a new key

My goal within the $set operation is to update a field only if it already exists. While $cond seems to be on the right track, it has the drawback of always creating the field, which is not what I want. Filtering to retrieve only existing fields seems like ...

The POST method in XHR encounters issues on IOS when used with the Canvas to Blob script

Observation I've noticed a specific part of the code that's not functioning correctly only on IOS devices. xhr.open('POST', 'upload.php', true); xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); var da ...

Using jQuery to send a JSON-encoded request containing multiple objects

I need help with a project I am working on. I currently have a running mariaDB server with a database and some tables, and I want to update the table entries using a web interface. To do this, I have created a PHP script as follows: <?php include &apo ...

Is there a way to use HTML alone to center a navigation link without using CSS?

Can I center these navigation links using only HTML without needing CSS? The navigation links are currently aligned to the left and I would like to center them on the webpage. <ul class="nav nav-tabs" id="myTab" role="tablist&q ...

"Incorporating Node.js (crypto) to create a 32-byte SHA256 hash can prevent the occurrence of a bad key size error triggered by tweetnacl.js. Learn how to efficiently

Utilizing the crypto module within node.js, I am creating a SHA256 hash as shown below: const key = crypto.createHmac('sha256', data).digest('hex'); However, when passing this key to tweetnacl's secretbox, an error of bad key siz ...

Is it possible to customize individual CSS attributes for a section within a webpage's layout using a view?

When I render a partial 'calendar/show' in two different views, I'm facing an issue. In view A, everything looks perfect with the right font sizes, but in view B, the font size appears too large. I'm looking for a way to adjust the fon ...