Vue Js - Transition only when component is visible - javascript

I'm doing some transitions using the transition tag and they're working perfectly. The problem is that transitions happen even if the component is not visible, I wanted it to happen only when the user arrived on that part of the page. Is there any way to do this with Vue?
HTML:
<transition name="products" appear>
<h2 class="container">Products</h2>
</transition>
CSS:
#keyframes slide-in {
from { transform: translateX(-60px); }
to { transform: translateX(0); }
}
.products-enter-active {
animation: slide-in 2s ease;
}

Related

vue transition component doesn't work correctly

hello this is a simple code but i don't know what is problem.
when i click on open modal on parent component modal get open but without transition
i just write it from a tutorial and in tutorial it work correctlry
<template>
<div class="backdrop" #click="$emit('close')" v-if="open"></div>
<transition name="modal" mode="out-in">
<dialog open v-if="open">
<slot></slot>
</dialog>
</transition>
</template>
<script>
export default {
emits: ['close'],
props:['open']
};
</script>
<style scoped>
.modal-enter-active{
animation: modal 2s linear;
}
.modal-leave-active{
animation: modal 2s linear;
}
#keyframes modal {
from{
opacity: 0;
transform:translateY(-150px) scale(0)
}
to{
opacity: 1;
transform:translateY(0) scale(1)
}
}
</style>
i am using vue 3
Do you actually need to use CSS animations?
How about using simple transitions?
.modal-enter-active, .modal-leave-active {
transition: 2s;
transition-timing-function: linear;
}
.modal-enter, .modal-leave-to {
opacity: 0;
transform:translateY(-150px) scale(0);
}

VUE :Transition elements on view change

I have what seems to be the simplest of problems but cannot get around it.
My goal is very simple :
On view change I would like to transition some elements of the new view. Not the whole view, because I want to keep the background in place, so a <router-view> global transition doesn't do the trick here (it works btw).
Here is an simplified version of the code I have right now :
<template>
<div class="fixedBackground">
<transition name="slideIn">
<div>
<h1>Title</h1>
<p>Subtitle</p>
</div>
</transition>
</div>
</template>
<script>
export default {
name: 'whatever'
}
</script>
<style scoped>
.slideIn-enter-active, .slideIn-leave-active {
transition: transform .3s ease, opacity .3s ease;
}
.slideIn-enter, .slideIn-leave-to {
transform: translateX(-10vw);
opacity: 0;
}
.slideIn-enter-to, .slideIn-leave {
transform: translateX(0);
opacity: 1;
}
</style>
The transition as it is doesn't have any effect.
I tried watching routes in App.vue to pass the active page as a prop and activate the transition when landing on the page, it didn't work.
And now that I'm experimenting with even more complicated solutions it just feels like I'm missing the really easy way to do that :( by what I've read the code I have should work fine.
TLDR : I need to transition some elements on view change, but not the whole router-view.
You need a v-if or v-show inside your transition, a data variable, "show" in this example, to toggle visibility, and then toggle the "show" variable on created, or any other action like data returned from an API, etc.
<template>
<div class="fixedBackground">
<transition name="slideIn">
<div v-show="show">
<h1>Title</h1>
<p>Subtitle</p>
</div>
</transition>
</div>
</template>
<script>
export default {
name: 'whatever',
data () {
return {
show: false
}
},
mounted () {
this.show = true;
}
}
</script>
<style scoped>
.slideIn-enter-active, .slideIn-leave-active {
transition: transform .3s ease, opacity .3s ease;
}
.slideIn-enter, .slideIn-leave-to {
transform: translateX(-10vw);
opacity: 0;
}
.slideIn-enter-to, .slideIn-leave {
transform: translateX(0);
opacity: 1;
}
</style>

CSS animation suddenly ends

I created a spinner animation. On click on spinner, JS adds class "loading" and it starts rotating. But if I remove this class it returns to the previous position without animation.
I tried to use this:
animation-fill-mode: forwards;, but result was the same.
There is my CSS:
.loading {
animation: spin 1s linear infinite 0s forwards;
}
#keyframes spin{
from{
transform: rotate(0deg)
}
to{
transform: rotate(360deg)
}
}
And HTML:
<i class="material-icons refresh-icon" onclick="$(this).toggleClass('loading');">refresh</i>
Thanks for your suggestions. I did it using JS and animationiteration event.
HTML:
<div class="spinner">
<i class="material-icons refresh-icon" onclick="spinner(this)">refresh</i>
</div>
JS:
const spinner = el => {
if($(el).hasClass('lock')) return;
if($(el).hasClass('loading')){
$(el).addClass('lock').one('animationiteration webkitAnimationIteration', function() {
$(el).removeClass('loading').removeClass('lock');
});
}else{
$(el).addClass('loading');
}
}
Link to codepan: https://codepen.io/nenazarko/pen/zYGPoZy

Vue.js animations not working correctly

I am using Vue 2 and attempting to include CSS animations on elements that are created and destroyed frequently. Below is an example of my code:
export default {
name: 'MyElement',
methods: {
enterStart: function (el) {
console.log('about to enter');
el.classList.add('testing-enter');
},
enter: function (el) {
console.log('entered');
},
leaveStart: function (el) {
console.log('starting to leave!');
},
leave: function (el) {
console.log('leaving!');
},
}
};
.testing-enter {
animation: enter .2s;
}
.testing-leave {
animation: leave .2s;
}
#keyframes enter {
0% {
opacity: 0;
transform: scale(0);
}
100% {
opacity: 1;
transform: scale(1);
}
}
#keyframes leave {
0% {
opacity: 1;
transform: scale(1);
}
100% {
opacity: 0;
transform: scale(0);
}
}
<template>
<div>
<transition
#before-enter="enterStart"
#enter="enter"
#leave="leaveStart"
#leave-active="leave"
appear
>
<div>My element is here!</div>
</transition>
</div>
</template>
First off, none of this works unless I include appear in my <transition ...> element. I know that this makes the transition happen on initial rendering, but I want them to happen any time the element is created or destroyed.
Next, in my console. I can see enterStart and enter both run, but leaveStart and leave never run, even when the elements are destroyed. What am I doing wrong?
The element inside the transition needs a state (show or hide). Also your transition needs a name that must much the transition in the CSS and it should be named with
name="transitionName"
e.g:
new Vue({
el: "#app",
data: function() {
return {
showThisElement: false
}
},
methods: {
toggleShow: function() {
this.showThisElement = !this.showThisElement
}
}
});
.testing-enter-active {
animation: enter .2s;
}
.testing-leave-active {
animation: leave .2s;
}
#keyframes enter {
0% {
opacity: 0;
transform: scale(0);
}
100% {
opacity: 1;
transform: scale(1);
}
}
#keyframes leave {
0% {
opacity: 1;
transform: scale(1);
}
100% {
opacity: 0;
transform: scale(0);
}
}
<div id="app">
<div #click="toggleShow">Show/Hide</div>
<transition
name="testing">
<div v-if="showThisElement">My element is here!</div>
</transition>
</div>
In the codepen, click on 'show/hide' to toggle the transition.
http://codepen.io/anon/pen/WpZPJp
Problem solved!
So I took out the transition from the individual component and created a transition-group instead around the container component that rendered them.
Then, after a bit more reading I realized I wanted to add the mode="out-in" field to my transition-group so that the leaving components fully animate before the new ones are rendered.
I also looked at the HTML when the animations were supposed to be happening to see what classes Vue added. It looks like Vue added v-enter-active, v-enter-to, and v-leave-to. Instead of customizing any names I just stuck with those classes and added my animations to them in the styling.
Hopefully if anybody else wants a similar effect this helps them decrease their stress levels a bit...

Controlling horizontal scrolling when using waypoints.js

I am building a custom wizard form with waypoints. Something interesting is happening and I can't figure it out for the life of me.
My sample CODEPEN is showing 2 pages of the wizard process to show you what I mean.
When you hit the forward action button (search in the first page of the wizard), the waypoints slide from the right and the next page or screen shows. That would repeat on-forward and backwards if I click on the backward action button. That is working.
The problem I see is with the initial horizontal scrollbar. It shows on page load, which it's a problem because the user could just scroll to the next screen by dragging the scrollbar. I thought of giving it an overflow-x but it didn't fix the issue. The interesting thing is, if I click on the search button and the waypoint slides, the scroll bar disappears and gives me the desired effect! What gives?
I built the CODEPEN as close as possible to the real environment so that you guys can catch any conflict with other elements instead of isolating the problem.
Here is the related code just in case:
HTML:
<div id="content" class="content">
<div class="row page">
<!-- First page content here -->
</div>
<div class="row page2">
<!-- Second page content here -->
</div>
</div>
CSS:
.page, .page2 {
position: absolute;
top: 20px;
left: 10px;
width: 100%;
-webkit-transition: -webkit-transform 0.8s;
transition: -webkit-transform 0.8s;
transition: transform 0.8s;
transition: transform 0.8s, -webkit-transform 0.8s
}
.page {
-webkit-transform: translateX(0%);
transform: translateX(0%)
}
.show-page2 .page {
-webkit-transform: translateX(-100%);
transform: translateX(-100%)
}
.page2 {
-webkit-transform: translateX(100%);
transform: translateX(100%)
}
.show-page2 .page2 {
-webkit-transform: translateX(0%);
transform: translateX(0%)
}
JS:
(function () {
var body = $('#content'),
nav = $('.btn-waypoint'),
panels = $('#content');
nav.on('click', function (e) {
e.preventDefault();
var dest = $(this).data('panel-link');
body
.removeClass(function (index, css) {
// remove only classes start with show-
// http://stackoverflow.com/questions/2644299/jquery-removeclass-wildcard
return (css.match(/\bshow-\S+/g) || []).join(' ');
})
.addClass('show-' + dest);
});
}());
The closest fix I've tried to solve this is making page2 display:none on page load to eliminate the scrollbar and then making it visible on button click. That almost did it except a funky look happens between the waypoint sliding effect and the css fade effect. Here is the code for that:
JS
$( document ).ready(function() {
$('.page2').css('display', 'none');
$('[data-panel-link]').on('click', function(){
$('.page2').css('display', 'block');
});
});
Here is the link to my CODEPEN
Thanks in advance!
As it plays out the root of the problem is the hard positioning. The waypoint divs are natively in vertical position which they would obviously not produce a horizontal scrollbar. They are being forced to be side by side by position:absolute and the transform: translateX(-100%) and this creates the horizontal scrollbar. If the mousewheel is disabled via jQuery the scrollbar goes away, but it goes away vertically as well. So instead of fighting that battle, a better alternative is to use a different transition that looks good but doesn't require a side by side animation. A fade will do just nice:
Simply replace the css effects from translateX to the following:
.page, .page2{
position: absolute;
width:100%;
transition: opacity 1s ease-in-out;
-moz-transition: opacity 1s ease-in-out;
-webkit-transition: opacity 1s ease-in-out;
}
.page {
opacity: 1;
}
.show-page2 .page {
opacity: 0;
}
.page2{
opacity: 0;
}
.show-page2 .page2{
opacity: 1;
}

Categories