Spectator6
Spectator6

Reputation: 403

How to set a css animation class variable with Javascript/jQuery?

I've been implementing some CSS animations as named classes so I can easily add/remove any associated animation for an element, making it "available" for subsequent or repeat animations.

I'm dipping my toes into using CSS variables and it's currently throwing me for a loop. I'm trying to allow the user to rotate an active image in 90 degree increments. In the code example below, I'm showing only the positive 90 button click event.

*.scss

:root {
  --rotation-degrees: 90;
}

@keyframes rotate {
  100% {
    transform: rotate(var(--rotation-degrees)+'deg');
  }
}

.animation-rotate {
  --rotation-degrees: 90;
  // NOTE: I suspect the variable does not need to be supplied here, removing does 
  // not fix the issue, at least in isolation
  animation: rotate(var(--rotation-degrees)) 0.2s forwards;
}

*.js

let degrees = 0;
function rotate(degrees_increment) {
  degrees += degrees_increment;

  // The use of document.documentElement.style.setProperty is something I've seen 
  // used in many of the articles I've read as a means to "get to" the css variable, 
  // so I'm simply blindly copying it's use here   
  document.documentElement.style.setProperty('--rotation-degrees', degrees +'deg');
  $('#main-image-slider img').addClass('animation-rotate');
}

$('#rotate-right-button').on('click', function(event) {
  event.preventDefault();
  rotate(90);
});

Thank you in advance for any insights and help you can give!

Upvotes: 0

Views: 1804

Answers (3)

Ajit Kamble
Ajit Kamble

Reputation: 11

I think the highlighted code is not triggering the animation again when adding a class - Existing Code

var angle = 0;

$("#rotate").click(function(e){
	angle+= 90;
  document.documentElement.style.setProperty('--deg', angle+'deg');
  var el = $(".square");
  var newone = el.clone(true);           
 	el.before(newone);        
 $(".square:last").remove();
});
:root {
  --deg: 180deg;
}

@keyframes rotate {
 100% {transform: rotate(var(--deg));}
} 
.animation-rotate {
  animation: rotate 0.9s forwards;
}

.square {
  background: hsl(300, 90%, 52%);
  width: 15vmin;
  height: 15vmin;
  border-radius: 10%;
  margin: 25px;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="square animation-rotate"></div>
  <div>
    <button class="btn btn-sm btn-success" id="rotate">Rotate</button>
  </div>
</div>

Upvotes: 1

sol
sol

Reputation: 22949

I don't think it's possible to concatenate a CSS variable with a string as you were trying in your CSS:

 transform: rotate(var(--rotation-degrees)+'deg');

It's better to handle that with JavaScript.

I think the main issue you're having is that the class needs to be removed after the animation has run (in order for it to be able to run again). You can do that with the animationend event listener.

Demo below:

const DIV = $('div');
const BUTTON = $('#rotate-right-button');
const SPAN = $('#variable-value');
const PROPERTY_NAME = '--rotation-degrees';
const DEG = 'deg';
const ROOT = document.documentElement;
const ElementClass = {
  ROTATE_ANIMATION: 'animation-rotate'
}
const ROTATION_VALUE = 90;
const Event = {
  CLICK: 'click',
  ANIMATION_END: 'animationend'
}

let degrees = 0;

function rotate(degrees_increment) {
  degrees += degrees_increment;
  ROOT.style.setProperty(PROPERTY_NAME, degrees + DEG);
  
  SPAN.html(`${PROPERTY_NAME}: ${degrees + DEG}`);
}

BUTTON.on(Event.CLICK, function() {
  DIV.addClass(ElementClass.ROTATE_ANIMATION);
  DIV.on(Event.ANIMATION_END, function(event) {
    $(this).removeClass(ElementClass.ROTATE_ANIMATION);
  });
  
  rotate(ROTATION_VALUE);
});
@keyframes rotate {
  100% {
    transform: rotate(var(--rotation-degrees));
  }
}

.animation-rotate {
  animation: rotate 0.2s;
}

div {
  background: red;
  width: 100px;
  height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>
<button id="rotate-right-button">rotate</button>
<br>
<span id="variable-value"></span>

Upvotes: 1

mrtnmgs
mrtnmgs

Reputation: 1562

I'm not sure I understand your code, but here's my take on it.
When the user clicks, you can either:
- add/remove a CSS class. In that case the values for the rotation are already set in your CSS.
- rotate the element directly in JavaScript, for instance by dynamically setting a CSS rule.

Seems to me like you're doing both at the same time?

Upvotes: 0

Related Questions