Reputation: 4787
I tried to set direction: 'reverse'
and also timeline.reverse()
, but it doesn't work. If I set loop: true
, then you can see the reverse animation in the loop. But I want to trigger it via e.g. a button. Here is a codepen for pure javascript and here is a version with vue.js.
function doFunction() {
var paths = [
{id: '#path309', d: 'm 55.184523,127.42857 34.962798,139.6183 43.46726,120.24702 z'},
{id: '#path311', d: 'm 54.389347,121.02185 -10.922087,-0.77483 11.717263,7.18155 z'}
];
var timeline = anime.timeline({ autoplay: true, direction: 'alternate', loop: false });
paths.forEach(function(path, index) {
timeline
.add({
targets: path.id,
d: {
value: path.d,
duration: 1000,
easing: 'easeInOutQuad'
},
offset: 1000 + 10 * index
});
});
}
<script src='https://cdnjs.cloudflare.com/ajax/libs/animejs/2.2.0/anime.min.js'></script>
<input id="clickMe" type="button" value="clickme" onclick="doFunction();" />
<svg xmlns="http://www.w3.org/2000/svg" width="100mm" height="100mm" viewBox="0 0 200 200">
<path d="m 110.51595,80.797791 26.28083,12.271789 2.96257,10.935445 z" id="path309" />
<path d="m 70.51595,80.797791 -5.00762,25.058566 11.28845,-2.786777 z" id="path311" />
</svg>
Upvotes: 3
Views: 1677
Reputation: 28722
By using timeline.reverse()
you can reverse the direction of the timeline to be animated.
I placed the timeline in an encompassing scope, so you don't have to rebuild the timeline on each click, and can just reverse it when a click occurs.
I also used an event Listener to bind the function, instead of an html inline event listener.
It is important, that you use animejs
v2.2.0, because the API in terms of offset
and timeline
has changed in newer versions, so this example will not work proper in newer versions.
Here is the pure JavaScript example:
/**
* We start in a scoped function to store our timeline there
*/
+function(button) {
/**
* A flag to know if we need to call reverse or not, we shouldn't on the first click
*/
var firstRun = true;
var paths = [
{id: '#path309', d: 'm 55.184523,127.42857 34.962798,139.6183 43.46726,120.24702 z'},
{id: '#path311', d: 'm 54.389347,121.02185 -10.922087,-0.77483 11.717263,7.18155 z'}
];
/**
* Disable the autoplay, we don't wanna jump the gun.
* Of if you do, remove the firstRun variable and if check.
*/
var timeline = anime.timeline({ autoplay: false, direction: 'alternate', loop: false });
paths.forEach(function(path, index) {
timeline
.add({
targets: path.id,
d: {
value: path.d,
duration: 1000,
/**
* I changed your chosen transform it because the delay
* your transform caused an almost second delay before
* it started animating.
*/
easing: 'easeInOutSine'
},
offset: 1000 + 10 * index
});
});
/**
* Listening to the click on the button
*/
button.addEventListener('click', function() {
/**
* If the animation has run, reverse the timeline
*/
if(!firstRun) {
timeline.reverse();
}
/**
* Play the animation!
*/
timeline.play();
/**
* We've run once. TIme to enable the reversing of the timeline.
*/
firstRun = false;
});
}(document.getElementById("clickMe"));
<script src='https://cdnjs.cloudflare.com/ajax/libs/animejs/2.2.0/anime.min.js'></script>
<input id="clickMe" type="button" value="clickme" />
<svg xmlns="http://www.w3.org/2000/svg" width="100mm" height="100mm" viewBox="0 0 200 200">
<path d="m 110.51595,80.797791 26.28083,12.271789 2.96257,10.935445 z" id="path309" />
<path d="m 70.51595,80.797791 -5.00762,25.058566 11.28845,-2.786777 z" id="path311" />
</svg>
And here is the vue.js
example:
new Vue({
el: '#app',
data() {
return {
timeline: anime.timeline({ autoplay: false, direction: 'alternate', loop: false }),
prepared: false,
switch1: false,
paths: [
{id: '#path309', d: 'm 55.184523,127.42857 34.962798,139.6183 43.46726,120.24702 z'},
{id: '#path311', d: 'm 54.389347,121.02185 -10.922087,-0.77483 11.717263,7.18155 z'}
]
}
},
watch: {
//called whenever switch1 changes
switch1(switchVal){
this.transform(switchVal)
}
},
methods: {
/**
* Call prepare later on, because otherwise the dom doesn't really seem initalized when the code isn't placed at the end of the document. Otherwise you can use created: to do this and a seperate flag for the first run.
*/
prepare: function() {
var timeline = this.timeline;
this.paths.forEach(function(path, index) {
timeline.add({
targets: path.id,
d: {
value: path.d,
duration: 1000,
easing: 'easeInOutSine'
}, offset: 1000 + 10 * index
})
});
this.prepared = true;
},
transform: function(direction) {
if(!this.prepared) {
this.prepare();
}
else {
this.timeline.reverse();
}
this.timeline.play();
}
}
})
#app {
padding-bottom:200px;
}
<link rel='stylesheet' href='https://unpkg.com/vuetify/dist/vuetify.min.css'>
<script src='https://unpkg.com/vue/dist/vue.js'></script>
<script src='https://unpkg.com/vuetify/dist/vuetify.min.js'></script>
<script src='https://unpkg.com/vue-i18n/dist/vue-i18n.js'></script>
<script src='https://unpkg.com/[email protected]/anime.min.js'></script>
<div id="app">
<svg
xmlns="http://www.w3.org/2000/svg"
width="100mm"
height="100mm"
viewBox="0 0 200 200"
>
<path d="m 110.51595,80.797791 26.28083,12.271789 2.96257,10.935445 z" id="path309" />
<path d="m 70.51595,80.797791 -5.00762,25.058566 11.28845,-2.786777 z" id="path311" />
</svg>
<v-switch
v-model="switch1"
label="Switch to transform and reverse"
color="green"
></v-switch>
</div>
Upvotes: 2