Vue.js Transition
Vue.js are o componenta <transition> in care se adauga elementul sau componenta pe care doriti sa o animati. Vue adauga automat trei clase CSS de intrare si trei de iesire.
v-enter
, v-enter-active
, si v-enter-to
sunt utilizate pentru tranzitia de intrare, cand componenta este introdusa sau activata.
v-leave
, v-leave-active
, si v-leave-to
sunt utilizate pentru tranzitia de iesire, cand componenta este dezactivata sau eliminata.
v-enter /v-leave si v-enter-to /v-leave-to definesc starile de inceput si sfarsit ale tranzitiei.
v-enter-active /v-leave-active definesc configuratia tranzitiei, cum ar fi durata, felul animatiei, etc.
Componenta <transition> poate avea un atribut name. Daca acesta e adaugat va inlocui prefixul v- in toate clasele.
De exemplu, daca e setat numele "tab", clasa v-enter
va deveni tab-enter
, asa si la celelalte.
- Sintaxa:
<div id='demo'>
<transition name='test'>
<div>Content</div>
</transition>
</div>
In elementul adaugat in
<transition> se poate folosi
v-if
si
v-show
pentru intrarea /iesirea tranzitiei. Apoi, in codul CSS se aplica proprietati pentru tranzitie /animatie la clasele CSS adaugate de Vue.
- Iata un exemplu simplu cu un buton si un tag H4 la care aplicam tranzitie CSS:
<style>
.cls_h {
color:#00e;
}
.test-enter-active, .test-leave-active {
transition: opacity 1s;
}
.test-enter, .test-leave-to {
opacity: 0;
}
</style>
<div id='demo'>
<transition name='test'>
<h3 v-show ='show' class='cls_h'>Ca sa am pace, dau pace.</h3>
</transition>
<button v-on:click='show = !show'>Show /Hide</button>
</div>
<script>
var vm = new Vue({
el: '#demo',
data:{ show:false }
});
</script>
In exemplul de sus aplicam stilul css pentru efect de tranzitie la clasele definite de Vue, dar cu prefixul "
test" (numele tagului <transition>):
.test-enter-active, .test-leave-active, .test-enter, .test-leave-to.
Tranzitie la Componente
In elementul <transition>
se pot adauga componente Vue personalizate.
- In exemplu urmator este definita o componenta Vue (aici "comp_test") si inclusa in <transition>:
<style>
.cls_h {
color:#00e;
}
.test-enter-active, .test-leave-active {
transition: opacity 1s;
}
.test-enter, .test-leave-to {
opacity: 0;
}
</style>
<div id='demo'>
<transition name='test'>
<comp_test v-show='show'></comp_test>
</transition>
<button v-on:click ='show = !show'>Show /Hide</button>
</div>
<script>
Vue.component('comp_test', {
props: ['show'],
data: function(){
return {msg:'Daruirea si primirea sunt una; Dau ceea ce vreau sa primesc.'}
},
template: "<h3 class='cls_h'>{{msg}}</h3>"
});
var vm = new Vue({
el: '#demo',
data:{show:false}
});
</script>
Tranzitie cu v-if si v-else
Se poate aplica tranzitie si la elemente adaugate cu v-if
si v-else
.
- Exemplu:
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>
<div id='demo'>
<transition name='fade'>
<h3 v-if='rest ==1'>This is in the tag with v-if, rest ={{rest}}.</h3>
<div v-else-if='rest ==2'>This is from v-else-if, rest ={{rest}}.</div>
<h4 v-else>This content is from v-else, rest not 1 or 2; rest ={{rest}}.</h4>
</transition>
Click to <button @click='altrElm'>Alternate elements</button>
</div>
<script>
var vm = new Vue({
el: '#demo',
data:{ rest:0, nr:0 },
methods:{
altrElm:function(){
this.nr++;
this.rest = this.nr %3;
}
}
});
</script>
Cand se face comutare intre elemente care au acelasi tip de tag, trebuie specificat sa sunt elemente distincte, adaugand un atribut key unic. Altfel, compilatorul Vue doar va inlocui continutul elementului.
Este indicat sa se adauge mereu atributul key cand sunt mai multe elemente in <transition>.
- Exemplu de sintaxa:
<transition>
<button v-if='is_save' key='save'>Save</button>
<button v-else key='edit'>Edit</button>
</transition>
Moduri de Tranzitie
Se poate aplica efect de tranzitie intre orice numar de elemente, fie folosind mai multe v-if
sau legand un singur element la o proprietate dinamica.
In tagul <transition> se poate adauga atributul mode
pentru a obtine efecte de tranzitie diferite.
Atributul mode poate avea unul din aceste doua valori: in-out
si out-in
.
- Testati exemplul urmator si inlocuiti "out-in" cu "in-out" ca sa vedeti diferenta.
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>
<div id='demo'>
Example with multiple <b>v-if</b>, without <b>mode</b> attribute:
<transition name='fade'>
<button @click='bState' v-if='b_state =="saved"' key='saved'>Save</button>
<button @click='bState' v-if='b_state =="edited"' key='edited'>Edit</button>
</transition>
<br><br>
Example with a single element binded to a dynamic property (here is_save), and <b>mode</b> attribute:
<transition name='fade' mode='out-in'>
<button @click='btnState' v-bind:key='is_save'>{{ btn_txt }}</button>
</transition>
</div>
<script>
var vm = new Vue({
el: '#demo',
data:{ b_state:'saved', btn_txt:'Save', is_save:true},
methods:{
//for example with v-if
bState: function(ev){
this.b_state = (this.b_state =='saved') ? 'edited' :'saved';
},
//for example with single element binded to is_save
btnState: function(ev){
this.is_save = !this.is_save;
this.btn_txt = this.is_save ? 'Save' :'Edit';
}
}
});
</script>
Animatie CSS cu Vue js
Animatia cu CSS se aplica in acelasi fel ca si tranzitia, diferenta fiind ca v-enter
nu este eliminat dupa ce elementul e introdus, ci pe un eveniment animationend.
- Iata un exemplu sa vedeti cum functioneaza animatia.
<style>
.cls_d {
background:#dadafe;
font-size:20px;
height:100px;
text-align:center;
width:180px;
}
@keyframes ex_anim {
0% { background:#fe1234; width:0;height:0; font-size:0;}
50% {
border-radius: 100%;
transform: rotate(180deg);
}
100% {
background:#bbbbfe;
transform: rotate(360deg);
transform: scale(1.05);
font-size:8px;
}
}
.ro_x-enter-active {
animation-name: ex_anim;
animation-duration: 1.5s;
}
.ro_x-leave-active {
animation: ex_anim reverse;
animation-duration: 1.5s;
}
</style>
<div id='demo'>
<transition name='ro_x'>
<div v-show ='show' class='cls_d'>Trecutul dispare, clipa ramane.<br>Cine sunt Eu?</div>
</transition>
<button v-on:click ='show = !show'>Show /Hide</button>
</div>
<script>
var vm = new Vue({
el: '#demo',
data:{ show:true }
});
</script>
Tranzitie cu redare initiala
Daca vreti ca animatia sa porneasca automat la incarcare, adaugati atributul appear
in tagul <transition>.
- Iata acelasi exemplu de animatie, dar cu atributul appear. In acest caz nu mai e nevoie de conditia v-show
.
<style>
.cls_d {
background:#dadafe;
font-size:20px;
height:100px;
text-align:center;
width:180px;
}
@keyframes ex_anim {
0% { background:#fe1234; width:0;height:0; font-size:0;}
50% {
border-radius: 100%;
transform: rotate(180deg);
}
100% {
background:#bbbbfe;
transform: rotate(360deg);
transform: scale(1.05);
font-size:8px;
}
}
.ro_x-enter-active {
animation-name: ex_anim;
animation-duration: 2s;
}
</style>
<div id='demo'>
<transition name='ro_x' appear>
<div class='cls_d'>Trecutul dispare, clipa ramane.<br>Cine sunt Eu?</div>
</transition>
</div>
<script>
var vm = new Vue({
el: '#demo'
});
</script>
Clase CSS personalizate pentru Tranzitie
Vue.JS ofera o lista de atribute care se adauga la elementul <transition> pentru definire clase personalizate pentru tranzitie.
- enter-class
- enter-active-class
- enter-to-class
- leave-class
- leave-active-class
- leave-to-class
Aceste atribute vor inlocui numele conventionale de clase.
Clasele personalizate sunt utile atunci cand dorim sa utilizam o biblioteca CSS externa, cum ar fi animate.css.
- Exemplu, folosim atributele
enter-active-class si
leave-active-class pentru a seta clase CSS pentru tranzitie (clase utilizate cu animate.css:
animated, tada, bounceOutRight):
<link href='//cdn.jsdelivr.net/npm/animate.css@3.5.1' rel='stylesheet' type='text/css'>
<div id='demo' style='text-align:center'>
<button @click='show = !show'>Toggle render</button>
<transition name='custom_cls' enter-active-class='animated tada' leave-active-class='animated bounceOutRight'>
<h3 v-if='show'>Iubesc Viata</h3>
</transition>
</div>
<script>
var vm = new Vue({
el: '#demo',
data: { show: true }
});
</script>
Durata de tranzitie explicita
Vue asteapta evenimentul transitionend si animationend sa detecteze daca animatia sau tranzitia s-a efectuat. Uneori asta poate cauza intarziere.
In astfel de cazuri se poate specifica o durata de tranzitie explicita (in milisecunde) folosind proprietatea :duration
in tagul <transition>:
<transition :duration='1000'>...</transition>
Or with separate values for enter and leave durations:
<transition :duration='{ enter:500, leave:800 }'>...</transition>
Clase de Tranzitie apelate ca Metode
Clasele de tranzitie pot fi apelate ca metode folosind atribute "JavaScript Hooks", definite cu v-on:
si numele evenimentului la care metoda e apelata.
- Sintaxa:
<transition
v-on:before-enter='beforeEnter' v-on:enter='enter'
v-on:after-enter='afterEnter' v-on:enter-cancelled='enterCancelled'
v-on:before-leave='beforeLeave' v-on:leave='leave'
v-on:after-leave='afterLeave' v-on:leave-cancelled='leaveCancelled'
>
HTML Elements
</transition>
Aceste atribute pot fi utilizate in combinatie cu tranzitii /animatii CSS, sau doar JavaScript.
Cand se creaza efect de tranzitie doar cu JavaScript, e necesara o functie callback pentru metodele enter si leave (vedeti in exemplu de mai jos). Altfel, metoda va fi apelata sincron si tranzitia se va termina imediat.
E bine sa adaugati v-bind:css='false'
pentru efectele de tranzitie facute doar cu JavaScript, astfel Vue poate sari peste detectarea CSS. In plus, impiedica regulile CSS sa interfereze cu tranzitia.
Exemplu, utilizare
Vue si velocity.js. Efectuam animatie la elementul <transition> doar cu metode js.
<div id='demo' style='text-align:center'>
<button @click='show = !show'>Toggle render</button>
<transition v-on:before-enter='beforeEnter' v-on:enter='enter' v-on:leave='leave' v-bind:css='false'>
<h3 v-if='show'>Iubesc Viata</h3>
</transition>
</div>
<script>
document.write('<sc'+'ript src="//cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></sc'+'ript>');
var vm = new Vue({
el: '#demo',
data: { show: false },
methods: {
beforeEnter: function(el){
el.style.opacity = 0
},
//done callback is optional when used in combination with CSS
enter: function(el, done){
Velocity(el, { opacity: 1, fontSize: '1.4em' }, { duration: 300 })
Velocity(el, { fontSize: '1em' }, { complete: done })
},
leave: function(el, done){
Velocity(el, { translateX: '15px', rotateZ: '50deg' }, { duration: 600 });
Velocity(el, { rotateZ: '100deg' }, { loop: 2 });
Velocity(el, { rotateZ: '45deg', translateY: '30px', translateX: '30px', opacity: 0 }, { complete: done });
}
}
});
</script>