Using Vuejs the data of some elements on the page is changing.
However, this change is not understood by the user.
For example, I am making a counter by clicking a button. I am printing data as {{counter}} to span element.
But this change is not noticed by the user. How can I give it various animations?
I tried to combine a css that I found have an animation I wanted, but was unsuccessful.
The Vuejs documentation says you can do it with toggleCss, but that's not what I want.
var app=new Vue({
el: "#app",
data: {
myCount:0
}
,
methods: {
btnCount() {
this.myCount+=1
}
}
})
<div id='app'>
<button #click='btnCount'>
+++++
</button>
<span class='myAnimSpan'>{{myCount}}</span>
</div>
span:hover {
animation: shake 0.5s;
}
#keyframes shake {
0% { transform: translate(1px, 1px) rotate(0deg); }
10% { transform: translate(-1px, -2px) rotate(-1deg); }
20% { transform: translate(-3px, 0px) rotate(1deg); }
30% { transform: translate(3px, 2px) rotate(0deg); }
40% { transform: translate(1px, -1px) rotate(1deg); }
50% { transform: translate(-1px, 2px) rotate(-1deg); }
60% { transform: translate(-3px, 1px) rotate(0deg); }
70% { transform: translate(3px, 1px) rotate(-1deg); }
80% { transform: translate(-1px, -1px) rotate(1deg); }
90% { transform: translate(1px, 2px) rotate(0deg); }
100% { transform: translate(1px, -2px) rotate(-1deg); }
}
Jsfiddle : https://jsfiddle.net/au4x031g/
You can use Vue transitions (see https://v3.vuejs.org/guide/transitions-enterleave.html#transitioning-single-elements-components).
Using a <transition> tag with name, and the element with key (each change to that key will trigger a transition update)
<transition name="shaketext">
<span class='myAnimSpan' :key="myCount">{{myCount}}</span>
</transition>
The name property is used for css declarations for enter/leave events, for example:
.shaketext-enter-active {
animation: shake 0.9s;
}
.shaketext-leave-to, .shaketext-leave-active{
display: none;
}
Also, to make transforms work, the span element should be a block element (display:inline-block for example)
.myAnimSpan {
display: inline-block;
}
https://jsfiddle.net/udctfs49/1/
Related
The transition element of vue only works with display:none but not visibility:hidden, is there any way to make it work with visibility? I want to get the clientWidth of the element before it shows up, with display:none I can't get that value.
By the way I'm using vue3.
Here is the reproduction demo:
https://codesandbox.io/s/competent-hermann-b1s5q
I'm going to assume, for the sake of argument, that you genuinely do need to use visibility for hiding and that other potential solutions (such as opacity) won't work in your real use case, possibly because they don't prevent user interactions with the element.
However, the assertion in the question is slightly misleading. It isn't really a difference between display and visibility. The real difference here is that the display case is using v-show, which includes special handling for transitions.
The current source code for v-show can be seen here:
https://github.com/vuejs/vue-next/blob/d7beea015bdb208d89a2352a5d43cc1913f87337/packages/runtime-dom/src/directives/vShow.ts
A similar approach can be used to construct a directive that uses visibility. Below is an example. It is based on the code for v-show but I've cut it back to just the code required for this particular use case:
const visible = {
updated(el, { value, oldValue }, { transition }) {
if (!value === !oldValue) {
return
}
if (value) {
transition.beforeEnter(el)
el.style.visibility = ''
transition.enter(el)
} else {
transition.leave(el, () => {
el.style.visibility = 'hidden'
})
}
}
}
Vue.createApp({
data() {
return {
show: true
};
},
methods: {
toggle() {
this.show = !this.show;
}
},
directives: {
visible
}
}).mount('#app')
#app {
text-align: center;
}
.tooltip-enter-active {
transition: transform 0.4s ease-out, opacity 0.3s ease-out;
}
.tooltip-leave-active {
transition: transform 0.35s ease-in, opacity 0.28s ease-out;
}
.tooltip-enter-from {
transition: none;
}
.tooltip-enter-from,
.tooltip-leave-to {
transform: translateY(-30px) scale(0.96);
opacity: 0;
}
<script src="https://unpkg.com/vue#3.0.2/dist/vue.global.prod.js"></script>
<div id="app">
<transition name="tooltip">
<div v-visible="show">
Using visibility
</div>
</transition>
<button #click="toggle">toggle message</button>
</div>
I did also have to make a small CSS change to give the enter transition a kick:
.tooltip-enter-from {
transition: none;
}
You'd probably be better off without <transition> in this case:
const app = Vue.createApp({
data() {
return {
show: true,
};
},
methods: {
toggle() {
const tooltip = this.$refs.tooltip;
this.show = !this.show;
tooltip.classList.toggle("tooltip-show");
},
},
mounted() {
console.log('Tooltip-width: ', this.$refs.tooltip.clientWidth);
},
});
app.mount('#app')
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.tooltip {
opacity: 0;
transform: translateY(-30px) scale(0.96);
transition: transform 0.35s, opacity 0.25s;
}
.tooltip-show {
opacity: 1;
transform: translateY(0) scale(1);
}
<script src="https://unpkg.com/vue#3.0.2/dist/vue.global.js"></script>
<div id="app">
<div class="tooltip" ref="tooltip">This will work!</div>
<button #click="toggle">toggle tooltip</button>
</div>
Target
On click "Open menu" button:
Dim overlay appearing with fade-in animation
Once dim overlay animation done, from the top, dim overlay is appearing with the sliding animation from the top to bottom:
Solution attempt and problem
<template lang="pug">
transition(name="fade")
.DrawerMenu-DimUnderlay(v-if="displayFlag")
.DrawerMenu-Body Drawer menu
</template>
Before slide down the .DrawerMenu-Body, .DrawerMenu-DimUnderlay must be mounted and rendered.
I don't know how to implement it.
🌎 Fiddle
You can achieve that by using CSS Animations and Vue Transition.
First, separate your overlay and content into different transitions:
<template lang="pug">
div
transition(name="overlay")
.DrawerMenu-Overlay(v-if="displayFlag")
transition(name="content")
.DrawerMenu-Body(v-if="displayFlag") Drawer menu
</template>
Then define your animations:
.DrawerMenu {
&-Overlay {
...
display: none;
}
...
}
.overlay-enter-active {
display: block;
animation: fade-in-and-slide-down 2s;
}
.content-enter-active {
animation: wait-and-fade-in 3s;
}
.content-leave-active {
animation: fade-out 1s;
}
#keyframes fade-in-and-slide-down {
0% {
opacity: 0;
}
50% {
opacity: 1;
transform: translateY(0);
}
100% {
transform: translateY(100%);
}
}
#keyframes wait-and-fade-in {
0% {
opacity: 0;
}
66% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#keyframes fade-out {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
Example in CodeSandbox.
Another solution is using JavaScript animation library (such as animejs) combine with Vue Transition Hooks. I would prefer this solution for a complex animation.
<template lang="pug">
transition(#enter='enter' #leave='leave')
div(v-if='displayFlag')
.DrawerMenu-Overlay(ref='overlay')
.DrawerMenu-Body(ref='content' #click="displayFlag = false") Drawer menu
</template>
import anime from "animejs";
...
methods: {
enter(el, done) {
anime
.timeline({
easing: "linear",
duration: 1000,
complete: done
})
.add({
targets: this.$refs.overlay,
opacity: [0, 1]
})
.add({
targets: this.$refs.overlay,
translateY: "100%"
})
.add({
targets: this.$refs.content,
opacity: [0, 1]
});
},
leave(el, done) {
anime({
targets: el,
duration: 2000,
opacity: 0,
complete: done
});
},
...
}
...
You can also use without transition component but you have to handle v-if variable by yourself.
Example in CodeSandbox.
Not sure if there are 2 questions here, but for your last question, I would say that is because that ref component does not have a property display.
It does however, have a function display()
Therefore, change your button click to this:
<button #click="$refs.drawerMenu.display()">Open menu</button>
I have a simple VueJS application where I have multiple routes. For a pair of routes, I want to have a scroll down and scroll up animation while routes change.
For example, I have a search/dropdown page, where after the search result from the dropdown is selected, I want to take him to the details page but with a scroll down animation. So that the user feels he is still on the same page.
I have tried using the VuePageTransition library. That is indeed a great library but does not have this specific animation that I need.
Update:
I tried the following code. It gives a scroll-like animation but the leaving page is shown going down but the coming page is not shown during the animation.
In the template in App.vue
<template>
<div id="app">
<transition name="slide" mode="out-in">
<router-view></router-view>
</transition>
</div>
</template>
In the style tag,
.slide-enter {
}
.slide-enter-active {
animation: slide-in-coming 2s ease-out forwards;
}
.slide-leave {
}
.slide-leave-active {
animation: slide-in 2s ease-out forwards;
}
#keyframes slide-in {
from {
transform: translateY(0);
}
to {
transform: translateY(800px);
}
}
#keyframes slide-in-coming {
from {
transform: translateY(-800px);
}
to {
transform: translateY(0);
}
}
Take a look at Basic form at Vuelidate documentation. If the rule is broken (text is too short), the label is red, then eror message appears and the input field shakes for a while. How is this done? I have copied the source code sample and the shaking effect is not there. I cannot even simulate it with an official fiddle: https://jsfiddle.net/so89zmpe/2/
<div class="form-group" :class="{ 'form-group--error': $v.name.$error }">
<label class="form__label">Name</label>
<input class="form__input" v-model.trim="$v.name.$model"/>
</div>
I cannot find anything relevant in Chrome developer
If you open DevTools > Animations tab, you can see that there's an animation name of shakeError applied on .form-group.form-group--error:
Here's the definition of shakeError:
#keyframes shakeError {
0% {
transform: translateX(0); }
15% {
transform: translateX(0.375rem); }
30% {
transform: translateX(-0.375rem); }
45% {
transform: translateX(0.375rem); }
60% {
transform: translateX(-0.375rem); }
75% {
transform: translateX(0.375rem); }
90% {
transform: translateX(-0.375rem); }
100% {
transform: translateX(0); } }
And then,
.form-group--alert,
.form-group--error {
animation-name: shakeError;
animation-fill-mode: forwards;
animation-duration: .6s;
animation-timing-function: ease-in-out; }
You can check the Sources tab of https://vuelidate.js.org/#sub-basic-form for a docs.scss file to dig in deeper.
I`m using Aurelia develop my project, When navigating, i want to add some transition between routes(e.g. fadeIn, fadeOut),but i don't know how to do it ? Thanks.
How to using aurelia-animator-velocity to implement the effects?
Using aurelia-animator-css.
You must put the style class="au-animate" on the topmost div in your route file. This must be the main div of the html template.
Sample router HTML
<template>
<div class="au-animate">
<div class="router-body">
<div class="router-list">
</div>
</div>
</div>
</template>
Sample animate CSS
#keyframes fadeOutRight {
100% {
opacity: 0;
transform: translate(100%, 0);
}
0% {
opacity: 1;
transform: none;
}
}
#keyframes fadeInRight {
100% {
transform: none;
}
0% {
transform: translate(-100%, 0);
}
}
.au-enter {
transform: translate(100%, 0);
}
.au-enter-active {
animation: fadeInRight 0.3s;
}
.au-leave-active {
animation: fadeOutRight 0.3s;
}
Aurelia Velocity
To add animations to specific elements:
<section anim-enter="fadeIn" anim-leave="fadeOut"></section>
<section anim-enter="{opacity:0};{duration:1000,easing:ease-out}"></section>
Use With JS
To use enter/leave animations on any element the animator has to be invoked manually.
To do this inject it into your VM an call the enter/leave methods.
import {VelocityAnimator} from "gooy/aurelia-animator-velocity";
export class MyCustomElement{
static inject = [Element,VelocityAnimator];
constructor(element,animator) {
this.element = element;
this.animator = animator;
}
attached(){
//run enter animation on the element
this.animator.enter(this.element);
//run leave animation on the element
this.animator.leave(this.element);
//run an effect on the element
this.animator.animate(this.element,"callout.bounce");
}
}
the answer will be aurelia-animator-css
here is a basic tutorial.