Reputation: 61
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
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
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
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