Vuetify transitions: How to set the transition speed - vue.js

I have an <audioplayer> component that I would like to be displayed slowly sliding from the bottom of a parent component.
I defined it inside <v-slide-y-transition>, but how I can make it slide slowly from the bottom? I cannot find any attributes to be defined for the <v-slide-y-transition> Vuetify component.
<v-parallax src="img/hero.jpeg">
<v-layout column align-center justify-center>
<img src="#/assets/images/logo.png" height="200">
<h1 class="mb-2 display-1 text-xs-center">HEADER 1</h1>
<h2 class="mb-2 display-1 text-xs-center">HEADER 2</h2>
<div class="subheading mb-3 text-xs-center">SUB-HEADER</div>
<v-btn round #click="switchAudioPlayer()" large href="#">LISTEN</v-btn>
<v-slide-y-transition>
<audioplayer id="audioplayer" v-if="listening" v-show="showAudioPlayer" :autoPlay="autoPlay" :file="audioFile" :canPlay="audioReady" :ended="switchAudioPlayer"></audioplayer>
</v-slide-y-transition>
</v-layout>
</v-parallax>

Vuetify transitions don't appear to have configuration properties, so you'd have to create your own in order to tweak the timing.
You could use a Vue <transition> component, using CSS transition property to set the timing of the animation.
For example, the following CSS sets the duration of the slide-fade animation to 2 seconds.
.slide-fade-enter-active {
transition: all 2s ease;
}
Demo:
new Vue({
el: '#app',
data: () => ({
show: false,
}),
})
.slide-fade-enter-active {
transition: all 2s ease;
}
.slide-fade-leave-active {
transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.slide-fade-enter, .slide-fade-leave-to
/* .slide-fade-leave-active below version 2.1.8 */ {
transform: translateY(30px);
opacity: 0;
}
footer {
position: absolute;
bottom: 0;
}
<script src="https://unpkg.com/vue#2.5.17"></script>
<div id="app">
<button v-on:click="show = !show">
Toggle
</button>
<footer>
<transition name="slide-fade">
<p v-if="show">hello</p>
</transition>
</footer>
</div>

If you use Vue 2.2.0+ the transition component has a duration prop so, it would look like this (if you use the vuetify transition name from your question):
<transition appear name="slide-y-transition" :duration="{ enter: 500, leave: 800 }>

Note: I noticed that you could add duration property to vuetify transition components. Its value is in milliseconds. But it's not very accurate, so I use it along with some CSS as below.
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
show: false,
}),
})
p {
background: lightgreen;
}
.slide-x-transition-enter-active {
background-color: #b2fab2;
transition: background-color 2s, all 2s;
}
.slide-x-transition-enter-to {
background-color: white;
}
.slide-x-transition-leave-active {
background-color: white;
transition: background-color 2s, all 2s;
}
.slide-x-transition-leave-to {
background-color: #fccece;
}
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<v-app id="app">
<button v-on:click="show = !show">
Toggle
</button>
<v-slide-x-transition duration="2000">
<p v-if="show">hello</p>
</v-slide-x-transition>
</v-app>

Related

Vuejs: How to add Transition to slot content?

I have a modal component that handles the overlay and css etc. and allows for modal content to be passed in via a slot:
<div class="slot-content">
<slot></slot>
</div>
And it's being used like
<Modal ...>
<div class="some-modal-content-div">
...
</div
</Modal>
Currently the modal appearance is a bit "abrupt".
I do want the overlay be there instantly, but would like to add a bit of a transition to the appearance of the content div.
How do I add a <Transition> to just the slot content?
If I understood you correctly maybe like following snippet:
const app = Vue.createApp({
data() {
return {
show: false,
};
},
})
app.component('modal', {
template: `
<div class="slot-content">
<p>other content</p>
<transition name="slide-fade" appear>
<slot></slot>
</transition>
</div>
`
})
app.mount('#demo')
.slide-fade-enter-active {
transition: all 0.5s ease-out;
}
.slide-fade-leave-active {
transition: all 1s cubic-bezier(1, 0.5, 0.8, 1);
}
.slide-fade-enter-from,
.slide-fade-leave-to {
transform: translateX(20px);
opacity: 0;
}
.mod {
border: 1px solid purple;
}
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
<button #click="show = !show">show</button>
<modal v-if="show" class="mod">
<div class="some-modal-content-div">
<b>slot content</b>
</div>
</modal>
</div>
I was actually too fixated on using the vue Transition instead of just applying the css animation directly to the slot content container:
<div class="slot-content animate-class">
<slot></slot>
</div>
...
.animate-class {
animation: foo 0.1s;
}

Transition vue router

I want a transition in my VueJS 3 project between 2 pages. I have a button and when I click on it, it goes on a new page with a dynamic URL. I would like a transition here. I don't have any errors but there is no transition when I change the page. I don't know why. It's true that initially I didn't had a <router-view/> tag, I had to add it to make the transition, maybe it doesn't use the router-view when it is changing the page so doesn't see the transition.
Here my code :
<template>
<div class="p-grid">
(...)
<div class="p-col" v-if="infoItem.length === 0">
</div>
<div v-else>
<router-link
:to=" {
name:
'Detail',
params: {
id: infoItem.name,
subcategory: infoItem.subcategory,
name: infoItem.name,
},
}">
<Button icon="pi pi-search-plus"></Button>
</router-link>
<router-view v-slot="{ Component }">
<transition name="route" mode="out-in">
<component :is="Component"></component>
</transition>
</router-view>
</div>
</template>
<script>
(
...)
</script>
<style>
.p-grid {
margin: 0.5rem;
font-family: "Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif;
}
/* Route transition */
.route-enter-from {
opacity: 0;
transform: translateX(100px);
}
.route-enter-active {
transition: ass 0.3s ease-out;
}
.route-leave-to {
opacity: 0;
transform: translateX(-100px);
}
.route-leave-active {
transition: ass 0.3s ease-in;
}
</style>
Do you any idea why ?
Thanks a lot

How do you apply Vue Transitions when Changing CSS Class?

I can't get Vue to apply Transition animation effects when changing from one CSS class to another (using V-bind).
I've gone through the Vue documentation but none of the examples work for my use case. I basically want the DIV to transition by fading nicely from full screen to "regular size" by toggling.
Please see Fiddle at https://jsfiddle.net/luckman8/892ktedz/
`
<div v-bind:class="{'fullscreen':isFullScreen, 'regularSize':!isFullScreen}">
<button type="button" #click="toggle">
Toggle
</button>
<p>
{{isFullScreen}}
</p>
</div>
`
The CSS:
.fade-enter-active, .fade-leave-active {
transition: opacity 3s ease-out;
}
.fade-enter, .fade-leave-to {
opacity: 0.1;
}
.regularSize
{
width: "50%";
height: "50%";
background-color: "green";
}
.fullscreen
{
display: flex;
flex-direction: column;
position: fixed;
background-color:blue;
top:0;
left:0;
width: 100%;
height: 100%;
flex-basis:10%;
overflow-y:hidden;
}
The Vue code:
new Vue({
el: "#app",
data: {
isFullScreen:false
},
methods: {
toggle()
{
this.isFullScreen = !this.isFullScreen
}
}
})
Thank you in advance!
The <transition> effects will only work for elements that change their visibility. So for example by using v-if.
So you have two options.
Either add a v-if logic to your template.
For example: (a quick mock up. could be refactored to be cleaner)
<div id="app">
<button type="button" #click="toggle">
Toggle
</button>
<transition name="fade">
<div
v-if="isFullScreen"
v-bind:class="{
'fullscreen':isFullScreen,
'regularSize':!isFullScreen
}">
<p>FULL SCREEN</p>
<button type="button" #click="toggle">
Toggle
</button>
</div>
</transition>
<transition name="fade">
<div
v-if="!isFullScreen"
v-bind:class="{
'fullscreen':isFullScreen,
'regularSize':!isFullScreen
}">
<p>SMALL SCREEN</p>
</div>
</transition>
</div>
Create the transition effect purely with css.

Transform Based Animation using Vue Transition Wrapper

I'm trying to port some animation implemented mostly through css and little javascript to a Vue component. The animation is simple - user clicks a button and a little panel opens from the bottom of his browser and slides upwards.
I have a working Vue component implemented using the same css and no javascript.
Now, I'm aware of the transition wrapper that Vue provides. But I'm unable to figure out how to get similar functionality using the transition wrapper (if at all).
Can someone help me out here?
// register modal component
Vue.component('modal', {
template: '#modal-template',
props: ['show']
})
// start app
new Vue({
el: '#app',
data: {
showModal: false
}
})
.drawer-wrapper {
position: fixed;
top: 100%;
left: 0;
right: 0;
height: 50%;
z-index: 9998;
transition: transform .3s ease-out;
}
.drawer-wrapper.open {
transform: translateY(-100%);
}
.drawer-container {
height: 100%;
width: 100%;
background-color: white;
}
.drawer-header h3 {
margin-top: 0;
color: #42b983;
}
.drawer-body {
margin: 20px 0;
}
.drawer-default-button {
float: right;
}
<script src="https://unpkg.com/vue#latest/dist/vue.js"></script>
<!-- template for the modal component -->
<script type="text/x-template" id="modal-template">
<div class="drawer-wrapper" :class="{ open: show }">
<div class="drawer-container">
<div class="drawer-header">
<slot name="header">
default header
</slot>
</div>
<div class="drawer-body">
<slot name="body">
default body
</slot>
</div>
<div class="drawer-footer">
<slot name="footer">
default footer
<button class="drawer-default-button" #click="$emit('close')">
OK
</button>
</slot>
</div>
</div>
</div>
</script>
<!-- app -->
<div id="app">
<button id="show-modal" #click="showModal = true">Show Modal</button>
<!-- use the modal component, pass in the prop -->
<modal #close="showModal = false" :show="showModal">
<!--
you can use custom content here to overwrite
default content
-->
<h3 slot="header">custom header</h3>
</modal>
</div>
I got this to work using a transition wrapper, but the code isn't as elegant as I'd expected. Particularly the use of the following attributes in the drawer-wrapper class:
top: 100%;
transform: translateY(-100%);
Fiddle is here
If anyone can simplify the code further, I'd really appreciate it.

Create sliding left effect using Vuejs animation

I've read this official document about Vuejs animation. But using it css hooks, I can only make element appear/disappear with fade and different duration.
<div id="demo">
<button v-on:click="show = !show">
Toggle
</button>
<transition name="fade">
<p v-if="show">hello</p>
</transition>
</div>
.fade-enter-active, .fade-leave-active {
transition: opacity .5s
}
.fade-enter, .fade-leave-to /* .fade-leave-active in <2.1.8 */ {
opacity: 0
}
How to use Vuejs Animation to create a sliding effect? Like the one here. Is it possible? Please provide some sample code.
You can absolutely do this with VueJS.
Have a look at the example under. You can see two examples, one is the adopted code for your case(to make it slide). And other is a simple image slider, that loops through array of images in 3 seconds interval.
Important thing to note here, is that we wrap the image element in for loop to force the element to be destroyed, because otherwise your elements will not be removed from DOM and will not transition (virtual DOM).
For better understanding of transitions in VueJS in recommend you to check out getting started guide - transition section.
new Vue({
el: '#demo',
data: {
message: 'Click for slide',
show: true,
imgList: [
'http://via.placeholder.com/350x150',
'http://via.placeholder.com/350x151',
'http://via.placeholder.com/350x152'
],
currentImg: 0
},
mounted() {
setInterval(() => {
this.currentImg = this.currentImg + 1;
}, 3000);
}
})
#demo {
overflow: hidden;
}
.slide-leave-active,
.slide-enter-active {
transition: 1s;
}
.slide-enter {
transform: translate(100%, 0);
}
.slide-leave-to {
transform: translate(-100%, 0);
}
.img-slider{
overflow: hidden;
position: relative;
height: 200px;
width: 400px;
}
.img-slider img {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right:0;
}
<!DOCTYPE html>
<html>
<head>
<title>VueJS 2.0 - image slider</title>
<link rel="stylesheet" href="style.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
</head>
<body>
<div id="demo">
<button v-on:click="show = !show">
Toggle
</button>
<transition name="slide">
<p v-if="show">{{message}}</p>
</transition>
<h3>
Img slider
</h3>
<transition-group tag="div" class="img-slider" name="slide">
<div v-for="number in [currentImg]" v-bind:key="number" >
<img :src="imgList[Math.abs(currentImg) % imgList.length]"/>
</div>
</transition-group>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script src="script.js"></script>
</body>
</html>
Thanks for the answer above it helped me a lot!
Since the original example had buttons to slide in both directions,
I improved it somewhat by adding "Next" and "Previous" buttons. I swap the animation to have it go the oposite way when pressing "Previous":
new Vue({
el: '#demo',
data: {
back: false,
currentIndex: 0
},
methods: {
next(){
this.back = false;
this.currentIndex++;
},
prev(){
this.back = true;
this.currentIndex--;
}
},
})
#demo {
overflow: hidden;
}
.slide-leave-active,
.slide-enter-active {
transition: 1s;
}
.slide-enter {
transform: translate(100%, 0);
}
.slide-leave-to {
transform: translate(-100%, 0);
}
.slideback-leave-active,
.slideback-enter-active {
transition: 1s;
}
.slideback-enter {
transform: translate(-100%, 0);
}
.slideback-leave-to {
transform: translate(100%, 0);
}
.div-slider{
overflow: hidden;
position: relative;
height: 100px;
width: 90%;
}
.div-slider .card {
position: absolute;
height: 100px;
width: 90%;
background-color: #60adff;
}
<!DOCTYPE html>
<html>
<head>
<title>VueJS 2.0 - image slider</title>
<link rel="stylesheet" href="style.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
</head>
<body>
<div id="demo">
<h3>
div slider
</h3>
<transition-group tag="div" class="div-slider" :name="back? 'slideback' : 'slide'">
<div v-if="currentIndex === 0" key="1">
<div class="card">
DIV 1
</div>
</div>
<div v-if="currentIndex === 1" key="2" >
<div class="card">
DIV 2
</div>
</div>
<div v-if="currentIndex === 2" key="3" >
<div class="card">
DIV 1
</div>
</div>
</transition-group>
<button #click="prev()" >prev</button>
<button #click="next()">next</button>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
</body>
</html>