4

I try to make a rotationg block, which rotation speed is controlled by <input type="range". The problem is that I can't find solution that doesn't restart animation when speed updates.

I tried three variants:

  • Directly set CSS animation speed by JS. — restarts animation;

  • jQuery's animate — doesn't work with transforms;

  • Library anime.js — it has method for speed changing but it also restarts animation (or just makes block jump, it's unclear)

What method allows to create smoothly changing by JS animation?

let block = anime({
   targets: '#transforms .block',
   rotateY: '360',
   easing: 'linear',
   loop: true,
   duration: 1000,
});


var el = document.querySelectorAll('#range')[0];

el.addEventListener('change', function() {  
  // console.log(value);
  // console.log(pos);
  var value = this.value;
  anime.speed = value/20;
  // console.log(block);
})
.block {
  width: 500px;
  height: 300px;
  background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/2.2.0/anime.js"></script>
<div id="transforms">
  <div class="block"></div>
</div>

<input id="range" type="range" min="0" max="20" step="1" value="10">

anime.js example code On Codepen

Andrew Lohr
  • 5,380
  • 1
  • 26
  • 38
Maria Piaredryj
  • 1,584
  • 3
  • 16
  • 35
  • I'm trying to do the same. I got pretty close with Velocity.js by issuing the animate command multiple times with a loop. The only problem is that there's a delay between changing the speed and it actually taking effect. The animation is consistent at least, probably because it's only adjusting the speed after a complete 360 deg rotation. `Velocity(rotor, { rotateZ: 360, }, {duration: 5000, loop: true, easing: "linear"});` `Velocity(rotor, { rotateZ: 360, }, {duration: 1000, loop: true, easing: "linear"});` – partofthething Apr 21 '19 at 00:39

2 Answers2

0

With velocity-animate library you can do a trick this way:

Velocity.animate(this.yourElement, {
  rotateZ: `${angle}deg`,
  duration: yourSpeed

})

Oleksandr Oleksiv
  • 638
  • 1
  • 6
  • 10
  • Should I put it to `change` callback? Where to take `angle`? And why should I put it as a variable? – Maria Piaredryj Apr 24 '18 at 15:08
  • angle is needed for rotate direction and distance (how many degrees your element should rotate for). You don't need to put is as variable. I wrote it this way only for example – Oleksandr Oleksiv Apr 24 '18 at 15:11
  • I don't think Velocity "value functions" get updated a loop is started. From the docs: `Property values can be passed functions. These functions are called once per element — immediately before the element begins animating. Therefore, when looping/reversing, the functions are not repeatedly re-called. ` http://velocityjs.org/ – partofthething Apr 21 '19 at 00:26
0

I guess triggering the speed change at the end of the animation cycle is what you need. However with this package i was unable to attach a transitionend event listener to any of the two divs. It won't trigger. So digging into this library i suppose you may achieve a similar task by attaching a run property to the anime options object which takes a function as value and invokes it multiple times by passing a progress argument. Once this progress argument is 100 we can make our speed change operation if the speed has changed (newSpeed !== void 0).

Don' let void 0 confuse you. It's just a perfect undefined value which i prefer to use when comparing undefined values.

let block = anime({
   targets : '#transforms .block',
   rotateY : '360',
   easing  : 'linear',
   loop    : true,
   duration: 1000,
   run     : anim => anim.progress === 100 && newSpeed !== void 0 && (anime.speed = newSpeed, newSpeed = void 0)
});

var range    = document.getElementById('range'),
    newSpeed = void 0;  // perfect undefined

anime.speed = range.value/20;
range.addEventListener('change', function(e) {
                                   newSpeed = e.target.value/20;
                                 });
.block {
  width: 500px;
  height: 300px;
  background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/2.2.0/anime.js"></script>
<div id="transforms">
  <div class="block"></div>
</div>

<input id="range" type="range" min="0" max="20" step="1" value="10">
Redu
  • 25,060
  • 6
  • 56
  • 76