Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript/css transition only working first time

I'm attempting to make an svg spin around on the first click and then spin back to the original position on second click smoothly both times. I have the following code.

HTML:

<div class="quick-access">
  <div class="quick-access__toggle">
     <svg id="toggle-button" viewBox="0 0 100 100" >
       <path d="M 50 30 L 50 70" stroke="white" stroke-width="5"/>
       <path d="M 30 50 L 70 50" stroke="white" stroke-width="5"/>
     </svg>
  </div>
</div>

SCSS:

$colour-orange: #faab18;

.quick-access{
  position: absolute;
  bottom: 20px;
  right: 20px;
  &__toggle{
    width: 50px;
    height: 50px;
    border-radius: 50%;
    background: $colour-orange;
  }
}

.open{
  background: white;
  svg{
    transition-property: transform;
    transition-duration: 0.7s;
    path{
      stroke: $colour-orange;
    }
  }
}

.overlay{
  background: rgba(30,30,30,0.6);
}

JS:

$('.quick-access__toggle').on('click', function(){
  $(this).toggleClass('open');
  if($(this).hasClass('open')){
    $('#toggle-button').css('transform', 'rotate(225deg)');
  }else{
    $('#toggle-button').css('transform', 'rotate(0deg)');
  }

  $('body').toggleClass('overlay')
}) 

What I want to happen is the svg spins around to 225deg on click then on the second click it spins around to 0deg. Currently it spins to 225deg but on second click it doesn't spin around smoothly like the first click, it just resets back at it's original position. I thought the transition-property and transition-duration would do this but it only works for the first click. I've attempted doing js animations but it doesn't support transform and I'd rather not use a plugin or polyfill to make that work.


1 Answers

The problem is because you only add the transform rule once the open class is added to the element - yet the rotate() property is added at the same time, so there's no animation.

To fix this issue you need to define the transform rule on the default state of .quick-access__toggle. You can then simply toggle a CSS class on the element which amends the rotate() rule. The transition will then be smooth between the two states, and the JS code is much more succinct. Try this:

$('.quick-access__toggle').on('click', function() {
  $(this).toggleClass('open');
  $('body').toggleClass('overlay')
})
.quick-access {
  position: absolute;
  bottom: 20px;
  right: 20px;
}

.quick-access__toggle {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background: #faab18;
}

.quick-access__toggle svg {
  transition: transform 0.7s;
  transform: rotate(0deg);
}
.open {
  background: white;
}

.open svg {
  transform: rotate(225deg);
}

.open path {
  stroke: #faab18;
}

.overlay {
  background: rgba(30, 30, 30, 0.6);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="quick-access">
  <div class="quick-access__toggle">
    <svg id="toggle-button" viewBox="0 0 100 100">
      <path d="M 50 30 L 50 70" stroke="white" stroke-width="5"/>
      <path d="M 30 50 L 70 50" stroke="white" stroke-width="5"/>
    </svg>
  </div>
</div>

Note that I had to convert your SCSS to plain old CSS for the snippet to work, but it should be easy enough to convert back.

like image 189
Rory McCrossan Avatar answered Jun 20 '26 01:06

Rory McCrossan