Home > database >  Any way to update the duration of an animation set via element.animate without restarting the animat
Any way to update the duration of an animation set via element.animate without restarting the animat

Time:11-08

I'm developing a game engine in HTML5. Characters are div elements using an animated sprite for background. As sprite animation have fluid parameters and must be set by code, they can't be predefined in a static CSS definition, thus I use element.animate to set sprite animations to a given row at a given speed knowing my scales and frame counts.

// Applies the given frame and animation to the sprite
// Frame is an angle, clockwise direction: 0 = up, 1 = right, 2 = down, 3 = left
set_animation(frame, duration) {
    const scale_x = this.settings.sprite.scale_x * this.settings.sprite.frames_x;
    const pos_y = this.settings.sprite.scale_y * -frame;

    // Cancel the existing animation
    if(this.data_actors_self.anim) {
        this.data_actors_self.anim.cancel();
        this.data_actors_self.anim = null;
    }

    // Play the animation for this row or show the first frame if static
    if(duration > 0) {
        this.data_actors_self.anim = this.element.animate([
            {
                backgroundPosition: px([0, pos_y])
            }, {
                backgroundPosition: px([scale_x, pos_y])
            }
        ], {
            duration: duration * 1000,
            direction: "normal",
            easing: "steps("   this.settings.sprite.frames_x   ")",
            iterations: Infinity
        });
        this.data_actors_self.anim.play();
    } else {
        this.element.style.backgroundPosition = px([0, pos_y]);
    }
}

Obviously that's a snippet from an actor class function: this.element is the div, this.settings is an object with parameters to be used who's names should make sense in this context, the px() function is a simple converter to turn arrays into pixel strings for HTML (eg: [0, 0] to "0px 0px").

The issue I'm having: While I can always run this function to set a new animation, I want the ability to change the speed of the animation without resetting it. It doesn't need to be a smooth transition, for all I care the new speed can be applied at the next iteration... I only want to avoid a visual snap or any kind of reset upon applying the change. Once an animation is set, I have no idea how to access and update its duration parameter. Does anyone have any suggestions?

When using console.log on this.data.anim I'm rightfully told it's an animation object. I tried using JSON.stringify to get more information but nothing relevant is printed. this.data.anim.duration returns undefined so the setting must be stored under some other property. Even if I know that property, I'd like to be sure web browsers will agree with me changing it like this.data.anim.options.duration = new_duration.

CodePudding user response:

The value for the animation duration isn't in the Animation object itself but in the CSS animation-duration property for the Element: so this.data_actors_self.style.animationDuration = new_duration will do the job. It will however restart the animation if it is being played, but if I understand correctly that isn't a problem for you.

CodePudding user response:

You can wait for the end of an iteration before changing the animation duration if that is what is required.

This snippet only sets an event listener for animationiteration event when you click the button to increase the speed.

function upthespeed() {
  const div = document.querySelector('div');
  div.addEventListener('animationiteration', function() {
    div.style.animationDuration = '1s';
  });
  document.querySelector('button').style.display = 'none';
}
div {
  width: 10vmin;
  height: 10vmin;
  background-color: magenta;
  animation: move 10s linear infinite;
}

@keyframes move {
  0% {
    transform: translateX(50vw);
  }
  50% {
    transform: translateX(0);
  }
  100% {
    transform: translateX(50vw);
  }
}
<div></div>
<button onclick="upthespeed()">Click me to increase the speed at the end of the next iteration (you may have to wait!)</button>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related