Vue transitions - vue.js

Dear developers, I have a question. Below code from Vue comonent
<transition-group name="fading">
<div v-for="item, id in b_data" :id="id" :dataName="item" v-if="address == item" class="card-body transition" key="d">
<p class="text-info align-middle">{{ item }} address</p>
</div>
</transition-group>
and this is code does't work. But if I change v-if to v-show all work properly. Why?
Code with v-show
<transition-group name="fading">
<div v-for="item, id in b_data" :id="id" :dataName="item" v-if="address == item" class="card-body transition" key="d">
<p class="text-info align-middle">{{ item }} address</p>
</div>
</transition-group>
and css code:
.fading-enter,
.fading-leave-to
{
opacity: 0;
}
.fading-enter-active
{
-webkit-transition: all 1.5s ease-in-out;
-moz-transition: all 1.5s ease-in-out;
-ms-transition: all 1.5s ease-in-out;
-o-transition: all 1.5s ease-in-out;
transition: all 1.5s ease-in-out;
animation: bounce-in 1s;
}
.fading-leave-active
{
animation: bounce-in 1s reverse;
}
#keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.5);
opacity: .5;
}
100% {
transform: scale(1);
opacity: .2;
}
}
What I doing wrong? Why v-if doesn't work?

Related

how to delay elements entering the DOM using TransitionGroup?

The problem I am running into is that all the elements are rendered first before the animation starts. The effect that I want to achieve is that the element is animated while entering the DOM and it happens one after another. What's wrong with my code?
<template>
<TransitionGroup appear name="stagger" tag="ul">
<li v-for="(num, index) in list" :style="{ '--order': index }" :key="num">
{{ num }}
</li>
</TransitionGroup>
</template>
<script setup>
const list = Array.from({ length: 5 }, (_, index) => index + 1);
</script>
<style scoped>
.stagger-enter-active {
animation-name: stagger;
animation-duration: 0.5s;
animation-delay: calc(var(--order) * 0.15s);
}
#keyframes stagger {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style>
After reading the official doc one more time, I realized that the same animation effect can be made with just transition and it works, which got me wondering what's the main difference between these two approaches?
.stagger-enter-from {
opacity: 0;
transform: translateX(-1em);
}
.stagger-enter-active {
transition: opacity 0.5s linear, transform 0.5s ease;
transition-delay: calc(var(--order) * 0.15s);
}

Make div follow slide transition in vue

When using transitions and v-if, it seems that the div is created and then animation happens within that div. Is it possible to make div follow the text during the animation?
Example provided, when clicking on the button, the button jumps to side and then text slides into meet it. What I'm aiming for is the button to slide with text when button is clicked.
Example: https://codepen.io/tadhglydon/pen/WNyVQZa
<div id="app">
<div class="container"><div class="filler"></div>
<button v-on:click="SlideIn">Test</button>
<transition name="slide">
<div v-if="toggle">Status update</div>
</transition>
</div>
</div>
.container {
width: 200px;
height: auto;
display: flex;
}
.filler{
flex-grow: 1;
}
.slide-leave-active,
.slide-enter-active {
transition: 1s;
}
.slide-enter {
transform: translate(100%, 0);
}
.slide-leave {
transform: translate(-100%, 0);
}
var app = new Vue({
el: "#app",
data: {
toggle: false
},
methods: {
SlideIn: function () {
this.toggle = !this.toggle;
}
}
});
Fixed this by using CSS and letting Vue controlling the transitions.
In the HTML I have
<div class="slider" :class="toggle ? 'slided' : ''">
And then in the CSS I have:
.slider {
width: 0px;
overflow: hidden;
transition: width 900ms ease;
-moz-transition: width 900ms ease;
-ms-transition: width 900ms ease;
-o-transition: width 900ms ease;
-webkit-transition: width 900ms ease;
}
.slided {
width: 100px;
}

How to use Vue transition to expand and shrink a div

Using Vue, I have two divs that I want to toggle with a transition. I want slowly expand the div to my desired width on click, and then shrink on another click. I can get the div to expand on one click, but can't figure out how to shrink it on the second click.
Not really clear if just specifying the width of the divs is enough, or if I also have to specify the same width in the css transition classes.
This fiddle shows what I've been trying: https://jsfiddle.net/vxmh8auo/1/
JS
new Vue({
el: '#app',
data: {
showButton: true
},
methods: {
randomise () { this.n = Math.random() }
},
components:{'input-div':blah}
});
CSS
.interaction {
border: 10px solid lightgreen;
display: flex;
flex: 1 0 auto;
max-height: 225px;
transition: max-height 0.25s ease-out;
}
.default {
width: 20px;
}
.bigger{
width: 200px;
}
.expand-enter-active, .expand-leave-active {
transition-property: width;
transition-duration: 5s;
}
.expand-leave-to {
width: 200px;
}
.expand-enter{
width: 20px;
}
HTML
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<div class="interaction">
<button #click="showButton=!showButton">
<transition name="expand" mode="out-in">
<div v-if="showButton" v-bind:class="showButton ? 'default':'bigger'" key="small"> B </div>
<div v-else class="bigger" key="big"> Bigger </div>
<!--<input-div><</input-div>-->
</transition>
</button>
</div>
</div>
You can do something like this, add class 'default' and toggle class 'bigger':
<button #click="toggleBigger">
<transition name="expand" mode="out-in">
<div class="default" v-bind:class="{ bigger: showButton }" key="small"> B </div>
<!--<input-div><</input-div>-->
</transition>
</button>
Add method toggleBigger, its more readable this way:
methods: {
toggleBigger(){
this.showButton = !this.showButton;
}
And add transitions on your css classes directly like this:
.default {
transition: max-height 0.25s ease-out;
width: 20px;
transition-property: width;
}
.bigger{
transition: max-height 0.25s ease-out;
width: 200px;
transition-duration: 5s;
transition-property: width;
}
You can see working fiddle HERE
PS I did not removed unnecessary classes from fiddle.
This seems so hackey and containing a lot of unnecessary classes, but it works: https://jsfiddle.net/df70pk68/
Again, my use case is a button that expands to a component with an input box and then shrinks again. My solution was to immediately make the component opacity zero, then slowly shrink it. The prevents the input box from breaching the border of the shrinking div. I would love it if someone could figure out a more elegant way to do this....
HTML
<div id="app">
<div class="interaction">
<button #click="showButton=!showButton">
<transition name="fade" mode="out-in">
<div v-if="showButton" class="default" key="small"> B </div>
<input-div class="bigger" v-else><</input-div>
</transition>
</button>
</div>
</div>
CSS
.interaction {
border: 10px solid lightgreen;
display: flex;
flex: 1 0 auto;
max-height: 225px;
}
JS
const blah = Vue.component('input-div',{
template: '<div><input type="text" readonly></div>'
});
new Vue({
el: '#app',
data: {
showButton: true
},
components:{'input-div':blah}
});
.default {
width: 20px;
}
.bigger{
width: 250px;
}
.fade-leave-active {
transition: all 5s ease;
}
.fade-leave-to{
width: 300px;
}
.bigger.fade-leave-to{
width:20px;
opacity: 0
}
.bigger.fade-leave-active{
transition: opacity 0s ease;
transition: width 5s ease;
}
maybe you should forget vue's support on this, only use css3 can do that, and very simple.
first ,this is your div's code
<div id="my-div"></div>
#my-div{
transition: width 0.5s; /* this is the key code you need */
}
then, you can change the width of my-div use vue or js-dom or whatever, the magic thing will happen.

Transition an element on a route change

I'm trying to transition this svg across the page when the route changes.
I've tried setting a watcher so when route path is 'comp1':'comp2' it should animate depending on the result.
The transitionName changes correctly, but the animation isn't firing...
Would love some help to know if this is possible and If so where I'm going wrong?
Thanks
<template>
<div class="background">
<div class="background__content">
<transition :name="transitionName"
mode="out-in">
<figure class="background__shape--primary">
<svg viewBox="-5 -10 130 130">
<path d="m0 0, 120 0, -60 100Z">
</path>
</svg>
</figure>
</transition>
</div>
</div>
</template>
<script>
data(){
return {
transitionName: '',
}
},
watch: {
$route(to){
let path = to.path;
if(path === '/one'){
this.transitionName = 'comp1';
}
else {
this.transitionName = 'comp2';
}
}
},
</script>
<style>
enter code here
.comp1-enter-active{
transform: translate(20px, -50px);
transition-duration: 0.3s;
transition-property: transform;
transition-timing-function: ease;
}
.comp1-enter,
.comp1-leave-active{
opacity: 0;
transform: translate(20px, -50px);
transition-duration: 0.3s;
transition-property: transform;
transition-timing-function: ease;
}
.comp1-leave-active,
.comp1-enter {
opacity: 0;
animation-delay: 300ms;
transform:translate(-26px, 80px);
transition-duration: 0.3s;
transition-property: transform;
transition-timing-function: ease;
}
.comp2-enter,
.comp2-leave-active{
opacity: 0;
transform: translate(50px, 20px);
transition-duration: 0.3s;
transition-property: transform;
transition-timing-function: ease;
}
.comp2-leave-active,
.comp2-enter {
opacity: 0;
animation-delay: 300ms;
transform:translate(10px, 15px);
transition-duration: 0.3s;
transition-property: transform;
transition-timing-function: ease;
}
</style>
What you want to use is vue class bindings with just a regular div.
<div :class="currentTranstion">Your SVG</div>
computed: {
currentTransition: ()=>{
return{
comp1: router.currentRoute === one;
comp2: router.currentRoute === two;
}
}
}
This is not the most effcient way to do it but it is a breif idea
If you are cofused about css transtions w3schools explains it very well

How to use Vue JS transition "inside" another transition?

Say I have a normal transition, which works perfectly fine (following vue docs). But I would like to have another transition INSIDE that one.
So for example, an element slides in, but then the text within that fades in at the same time?
I can't get the inside child transition to animate. It's not getting fired? I've tried "appear" also thinking the node is new.
There's almost no information out there on this.
<div id="demo">
<transition name="slide">
<div v-if="show">
<transition name="slide-fade">
<p>hello</p>
</transition>
</div>
</transition>
</div>
Transition effects
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
.slide-fade-enter-active {
transition: all 0.3s ease;
}
.slide-fade-leave-active {
transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
}
.slide-fade-enter,
.slide-fade-leave-to {
transform: translateX(10px);
opacity: 0;
}
You did not seem to add the transition CSS for the slide component. The following should work:
const vm = new Vue({
el: '#demo',
data() {
return {
show: true
}
}
})
.slide-fade-enter-active,
.slide-fade-leave-active {
transition: opacity 0.5s;
}
.slide-fade-enter,
.slide-fade-leave-to {
opacity: 0;
}
.slide-enter-active {
transition: all 0.3s ease;
}
.slide-leave-active {
transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
}
.slide-enter,
.slide-leave-to {
transform: translateX(10px);
opacity: 0;
}
/* Some styling to make them noticeable */
.parent {
background-color: lightgray;
padding: 2px;
}
.child {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<transition name="slide">
<div v-if="show" class="parent">
<transition name="slide-fade">
<p class="child">hello</p>
</transition>
</div>
</transition>
<button #click="show = !show">Toggle</button>
</div>