Tijgerbrood
Tijgerbrood

Reputation: 61

How do I give an Anime.js element an opening animation first, and then a looping animation?

I'm trying to animate an object with Anime.js. It has an opening animation (rotate) that plays once, and after that it should have a different rotate animation which loops indefinitely. I put both thesse animations in a timeline, but it won't loop the second animation.

Javascript:

var tl = anime.timeline({

  easing: 'easeOutExpo',
  targets: '.fles',
});

tl

.add({
  rotate: 20,
  duration: 750,
  loop: false,
})

.add({
    duration: 6000,
    loop: true,
    easing: 'easeInOutQuad',
    keyframes: [
        {rotate: '+=1'},
        {rotate: '-=1'},
        {rotate: '+=1.5'},
        {rotate: '-=2'},
        {rotate: '+=1.5'},
    ],
})

Is this possible with Anime.js, and how?

Thanks in advance!

Upvotes: 2

Views: 2281

Answers (3)

liamlows
liamlows

Reputation: 613

Just wanted to follow up on @WerWet's answer, you can also do this with timelines. In my case I was applying a bunch of effects to an SVG and animating text on page load but wanted the text to glitch indefinitely after it finished the loading animation. Here is what I did...

(I'm using react thus animation() is called in the useEffect hook)

const animation = () => {
  const timeline = anime.timeline()
    timeline.add({
    targets: ".path",
    strokeDashoffset: [anime.setDashoffset, 0],
    easing: "easeInOutSine",
    duration: 1500,
    delay: function (el, i) {
      return i * 250
    },
  })
  timeline.add({
    targets: ".logo-main",
    duration: 20,
    skewX: 40,
    easing: "easeInOutQuad",
  })
  timeline.add({
    targets: ".logo-main",
    duration: 20,
    skewY: 40,
    easing: "easeInOutQuad",
  })
  timeline.add({
    targets: ".logo-main",
    duration: 20,
    skewX: -40,
    easing: "easeInOutQuad",
  })
  timeline.add({
    targets: ".logo-main",
    duration: 70,
    skewX: 0,
    skewY: 0,
    easing: "easeInOutQuad",
  })
  timeline.add({
    targets: ".logo-main",
    duration: 70,
    opacity: 0,
    easing: "easeInOutQuad",
  })
  timeline.add({
    targets: ".logo-main",
    filter: "drop-shadow(0px 0px 20px rgba(43, 251, 251, 1))",
    opacity: 1,
    easing: "easeInOutSine",
    duration: 1000,
    direction: "alternate",
  })
  timeline.add({
    targets: ".letter",
    opacity: [0, 0.75],
    translateY: [-600, 0],
    easing: "easeOutExpo",
    duration: 1400,
    delay: (el, i) => 50 * (i + 1),
    endDelay: 500,
  })

  timeline.play()
  timeline.finished.then(() => {
    const timelineText = anime.timeline({ loop: true })
    timelineText.add({
      targets: ".letter",
      duration: 70,
      skewX: 70,
      easing: "easeInOutQuad",
    })
    timelineText.add({
      targets: ".letter",
      duration: 70,
      skewX: 0,
      easing: "easeInOutQuad",
    })
    timelineText.add({
      targets: ".letter",
      duration: 7000,
    })
  })
}

Hope this helps!

Upvotes: 0

marcusstenbeck
marcusstenbeck

Reputation: 825

This may be solved by using an inner and an outer <div>. Place the looping animation on one of them, and the opening animation on the other.

<div id="outer">
  <div id="inner">
    Foo
  </div>
</div>
// opening animation
anime({
  targets: '#outer',
  scale: [0, 1],
  loop: false
});

// looping animation
anime({
  targets: '#inner',
  rotate: [-5, 5],
  loop: true,
  direction: 'alternate'
});

Upvotes: 1

WerWet
WerWet

Reputation: 383

It is not possible to do it with timelines, timeline just loops when you pass loop: true on its creation. From source code it seems that loop property in added objects is ignored.

However you can use promise .finished on anime instance:

anime({/*first animation*/}).finished.then(()=>
anime({/*next animation*/}))

and to mimic inheriting properties:

let base = {
  easing: 'easeOutExpo',
  targets: '.fles',
}

anime(Object.assign({}, base, {
  rotate: 20,
  duration: 750,
  loop: false,
}))
.finished.then(()=>
  anime(Object.assign({}, base, {
    duration: 6000,
    loop: true,
    easing: 'easeInOutQuad',
    keyframes: [
      {rotate: '+=1'},
      {rotate: '-=1'},
      {rotate: '+=1.5'},
      {rotate: '-=2'},
      {rotate: '+=1.5'},
    ],
  })));

Upvotes: 2

Related Questions