0

I want to change the animation attribute of my CSS class with a JavaScript function. I have been trying various methods but none of them worked. Please find out where I am going wrong.

CSS:

   .center {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 200px;
  height: 200px;
  border-radius: 50%;
  background: transparent;
}

.center .earth {
  position: absolute;
  top: 0;
  width: 200px;
  height: 200px;
  background-image: url(https://www.publicdomainpictures.net/pictures/90000/velka/earth-map.jpg);
  margin: 3em auto;
  border-radius: 50%;
  background-size: 630px;
  animation: spin 30s linear alternate infinite;
  box-shadow: inset 20px 0 80px 6px rgba(0, 0, 0, 1);
  color: #000;
}

.center .earth .moon {
  position: absolute;
  top: calc(50% - 1px);
  left: 50%;
  width: 200px;
  height: 2px;
  transform-origin: left;
  border-radius: 50%;
  animation: rotate 10s linear infinite;
}

.center .earth .moon::before {
  content: '';
  background-image: url(https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRsvjrANMGI8aBJSFbsHteVa04rcB1IjjNsbrhm8vTLflfpiG133g);
  position: absolute;
  background-size: 200px;
  top: -25px;
  right: 0;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  animation: spin 10s linear infinite;
}

@keyframes rotate {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

@keyframes spin {
  100% {
    background-position: 100%;
  }
}

HTML:

<div className="center">
      <div className="earth">
        <div className="moon" />
      </div>
    </div>

JavaScript function:

    function change() {
  var elem = document.getElementsByClassName('moon');
  elem.style.animation="rotate 5s linear infinite";
}

I have tried various methods but none of them are able to perform the modification. Looping through the object didn't help either.

2
  • className is not a valid HTML attribute. You probably meant to write <div class="moon"></div> instead. Commented Jun 17, 2018 at 22:37
  • @cfillion sorry I forgot to mention that I am working with React. Commented Jun 17, 2018 at 22:45

3 Answers 3

2

elem is an HTMLCollection of elements, not a single element, and setting the style property of the HTMLCollection doesn't work.

Instead, you'll want to change the style for each element individually:

Array.from(document.getElementsByClassName('moon')).forEach(elem => {
    elem.style.animationDuration = "5s";
});

EDIT:

Here's a snippet to show that the method works/provide a reference:

function change_spin_rate() {
  Array.from(document.getElementsByClassName('spinner')).forEach(elem => {
    elem.style.animationDuration = "1s";
  });
}

document.getElementById("spin_change").onclick = change_spin_rate;
@keyframes spin {
  from {
    transform: rotate(360deg);
  }
  to {
    transform: rotate(0deg);
  }
}

.spinner {
  display: inline-block;
  animation: spin 4s infinite linear;
}

#spin_change {
  padding: 8px 16px;
  display: inline-block;
  font-family: sans-serif;
  cursor: pointer;
  border-radius: 16px;
}

#spin_change:hover {
  background: rgba(0, 64, 255, 0.1);
}
<a class="spinner">🌀</a><a class="spinner">🌀</a><a class="spinner">🌀</a>

<a id="spin_change">Click me to change the spin rate for all spinners.<a>

<a class="spinner">🌀</a><a class="spinner">🌀</a><a class="spinner">🌀</a>

Sign up to request clarification or add additional context in comments.

4 Comments

I've added a snippet to demonstrate–it should work if there aren't other bugs... are you sure your change() function is getting called? Can you print the style rules for the modified elements in the change() function (console.log(elem.style.animationDuration)) and also check them in the web inspector (right click on one of the .moon elements and choose "Inspect Element" to see the associated CSS rules)? The JS style modifications should appear in the element's style attribute.
This is how I am calling the change function. <button onClick={change}> Click me to change the speed. </button>
It's not clear from that comment what exactly you have in the onClick attribute, but it should be onclick="change()". onclick="change" won't work, nor will the literal text onclick={change}. You can check if the change() function is executing by adding a console.log() to the start of the change() function definition and seeing if it shows up in the console.
Thank you very much for responding. It gets executed. I tried just alert() and it works. I am pretty sure onClick={change} is how we call a function in React JSX. Take a look at the entire code here: github.com/avinashredyy/Moon-Orbiting-Earth
1

document.getElementsByClassName returns multiple elements. You need to iterate through them and apply your change to each element.

function change() {
  Array.from(document.getElementsByClassName("moon")).forEach((elem) => {
    elem.style.animation = "rotate 5s linear infinite";
  });
}

document.getElementsByClassName doesn't return an array. You have to use Array.from on it before you can call Array.prototype.forEach.

By the way, <div className="moon" /> should be <div class="moon" /> unless you are writing React JSX.

4 Comments

This function could not modify the animation. Yes I am writing JSX.
I looked at your code: github.com/avinashredyy/Moon-Orbiting-Earth/blob/master/src/…. It should be ##onClick={this.change.bind(this)}##.
When I made this change it gave me an error saying "Cannot read property 'bind' of undefined"
Sorry. I didn’t pay attention to where you define the change function. It should be a class method like render.
0

try this:

function change() {
  let elems = document.getElementsByClassName("moon");
  elems.forEach(elem => elem.style.animation = "rotate 5s linear infinite");
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.