Aurelia Animation Not Kicking In - aurelia

I am trying to get some simple animiation to work with Aurelia;
First, I have the plug-in in main:
.plugin(PLATFORM.moduleName('aurelia-animator-css'))
Then I define some css for the animation:
.my-cool-element > .au-enter {
opacity: 0 !important;
}
.my-cool-element > .au-enter-active {
-webkit-animation: fadeIn 5s;
animation: fadeIn 5s;
}
.my-cool-element > .au-leave-active {
-webkit-animation: fadeOut 5s;
animation: fadeOut 5s;
}
#-webkit-keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#-webkit-keyframes fadeOut {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#keyframes fadeOut {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
Then I use it in the html:
<div class="my-cool-element">
<div class="au-animate">
<div if.bind="showMessage" class="navbar">${message}</div>
</div>
</div>
Then in code, I set showMessage=true and the element shows with the message, but it does not animiate.
But it doesn't animate. Am I missing something?

Turns out for the animation to work with if.bind, the au-animate class needs to be in the same element, like this:
<div class="my-cool-element">
<div if.bind="showMessage" class="au-animate">
<div class="navbar">${message}</div>
</div>

Related

use component variable in scss style

I have this kenburns gallery slideshow which I did statically and I would love to make it more dynamic now ...
so I have this component:
<template>
<div>
<div class="slideshow">
<v-img v-for="photo in photos" :key="photo.id_photo" :src="photo.full_img_path" class="slideshow-image"></v-img>
</div>
<Header></Header>
</div>
</template>
<script>
import Header from './shared/Header.vue';
import PublicService from './public.service';
export default {
name: 'Home',
components: {
Header
},
data: () => ({
serverHost: process.env.VUE_APP_API_BASE_URL,
photos: []
}),
created() {
this.getHomePagePhotos();
},
computed: {},
methods: {
getHomePagePhotos() {
PublicService.getHomePagePhotos().then(
result => {
this.photos = result?.data;
this.photos.forEach(p => {
p.full_img_path = this.serverHost + p.photo_path.replace('/uploads', '') + '/' + p.photo_name;
});
},
error => {
console.log(error);
}
);
}
}
};
</script>
<style lang="scss">
$items: 4;
$animation-time: 4s;
$transition-time: 0.5s;
$scale: 20%;
$total-time: ($animation-time * $items);
$scale-base-1: (1 + $scale / 100%);
.slideshow {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
.slideshow-image {
position: absolute;
width: 100%;
height: 100%;
background: no-repeat 50% 50%;
background-size: cover;
animation-name: kenburns;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-duration: $total-time;
opacity: 1;
transform: scale($scale-base-1) translateX(500px);
#for $i from 1 through $items {
&:nth-child(#{$i}) {
animation-name: kenburns-#{$i};
z-index: ($items - $i);
}
}
}
#for $i from 1 through $items {
#keyframes kenburns-#{$i} {
$animation-time-percent: percentage($animation-time / $total-time);
$transition-time-percent: percentage($transition-time / $total-time);
$t1: ($animation-time-percent * ($i - 1) - $transition-time-percent / 2);
$t2: ($animation-time-percent * ($i - 1) + $transition-time-percent / 2);
#if ($t1 < 0%) {
$t1: 0%;
}
#if ($t2 < 0%) {
$t2: 0%;
}
$t3: ($animation-time-percent * ($i) - $transition-time-percent / 2);
$t4: ($animation-time-percent * ($i) + $transition-time-percent / 2);
#if ($t3 > 100%) {
$t3: 100%;
}
#if ($t4 > 100%) {
$t4: 100%;
}
$t5: (100% - $transition-time-percent / 2);
$t6: (($t4 - $t1) * 100% / $t5);
#{$t1} {
opacity: 1;
transform: scale($scale-base-1) translateX(($i * 72px % 200px)-100px);
}
#{$t2} {
opacity: 1;
}
#{$t3} {
opacity: 1;
}
#{$t4} {
opacity: 0;
transform: scale(1);
}
#if ($i != $items) {
100% {
opacity: 0;
transform: scale($scale-base-1);
}
}
#if ($i == 1) {
$scale-plus: ($scale * (100% - $t5) / $t4);
$scale-plus-base-1: (1 + ($scale + $scale-plus) / 100%);
#{$t5} {
opacity: 0;
transform: scale($scale-plus-base-1);
}
100% {
opacity: 1;
}
}
}
}
</style>
And I wonder how do replace the very first scss variable
$items: 4;
with the actual number of items coming from the server
$items: this.photos.length;
I googled a lot but didn't find anything .. any idea?
As others have said I don't believe it's possible to set SASS variables in Vue 2. You can set CSS variables however I'm not sure if it's possible to implement those into what you're trying to achieve
https://shayneo.com/blog/binding-css-variables-with-vue/

How to display a component when page is loading in nuxt

I am quite new to nuxt, and I need help here.
async asyncData({ params, route }) {
const { data } = await axios.get(
`${process.env.baseUrl}/homes/?search=${
params.search
}&home_status=${1}`
)
return {
homes: data.results,
}
}
I am trying to populate my component with data(using asyncData), but I want my skeleton loader to show if my page is loading. How do I do that in nuxt?
Here is the code for my skeleton loader;
<template>
<div class="placeholder-container">
<div class="placeholder wave">
<div class="square"></div>
<div class="line"></div>
<div class="line"></div>
<div class="line"></div>
</div>
</div>
</template>
<style scoped>
.placeholder-container {
width: 35rem;
margin: 15px auto 15px auto;
}
.placeholder {
padding: 10px;
width: 100%;
// border: 1px solid lightgrey;
display: flex;
flex-direction: column;
}
.placeholder div {
background: #e8e8e8;
}
.placeholder .square {
width: 100%;
height: 22rem;
border-radius: 1rem;
margin: 0 0 10px;
}
.placeholder .line {
height: 12px;
margin: 0 0 10px 0;
}
.placeholder .line:nth-child(2) {
width: 120px;
}
.placeholder .line:nth-child(3) {
width: 180px;
}
.placeholder .line:nth-child(4) {
width: 150px;
}
.placeholder.wave div {
animation: wave 1s infinite linear forwards;
-webkit-animation: wave 1s infinite linear forwards;
background: #f6f7f8;
background: linear-gradient(to right, #eeeeee 8%, #dddddd 18%, #eeeeee 33%);
background-size: 800px 104px;
}
#keyframes wave {
0% {
background-position: -468px 0;
}
100% {
background-position: 468px 0;
}
}
#-webkit-keyframes wave {
0% {
background-position: -468px 0;
}
100% {
background-position: 468px 0;
}
}
</style>
What I normally do without using nuxt, is to create a data variable(loading=true), and change it to false after I finish making the api call, but since asyncData runs in the server, how do I make that work? I will also appreciate it if there is a better way of doing something like this
Placeholder
To display a placeholder component on a particular page
during loading, switch from asyncData to the fetch hook, which exposes the $fetchState.pending flag that is set to true when complete:
<template>
<div>
<MyLoading v-if="$fetchState.pending" />
<MyContent v-else :posts="posts" />
</div>
</template>
<script>
export default {
data() {
return {
posts: []
}
},
async fetch() {
const { data } = await this.$axios.get(...)
this.posts = data
}
}
</script>
Customizing loading progress bar
Nuxt provides a default loading progress bar that appears at the top of the app while a page is loading. You could customize the progress bar's appearance:
// nuxt.config.js
export default {
loading: {
color: 'blue',
height: '5px'
}
}
Or you could specify your own custom loading component instead:
// nuxt.config.js
export default {
loading: '~/components/MyLoading.vue'
}
demo

I want to create a custom loader in ionic 4 ,but in the message feild it is showing html code ,but not rendering my gif image

async presentLoading() {
const loading = await this.loader.create({
duration: 2000,
showBackdrop:false,
cssClass:'sa',
spinner:'false',
message:`
<div class="custom-spinner-container">
<img class="loading" width="120px" height="120px" src="assets/loader1.gif" />
</div>`
});
return await loading.present();
}
You can just simply achieve it with css
//Header of file
import { LoadingController } from "#ionic/angular";
//In the constructor
constructor(public loadingCtrl: LoadingController) {
}
async showLoader () {
this.loader = await this.loadingCtrl.create({
cssClass: 'custom-loader',
spinner: null
});
await this.loader.present();
}
/* Inside global.scss
You can create amazing gifs with
https://loading.io/animation
*/
.custom-loader {
--background: transparent;
ion-backdrop {
background-color: #fff;
opacity: .9 !important;
}
.loading-wrapper {
-webkit-animation: ld-vortex-out 2s ease-out infinite;
animation: ld-vortex-out 2s ease-out infinite;
animation-timing-function: cubic-bezier(0.05, 0, 3, 0.05);
background-image: url("/assets/img/baubap-logo-circle.svg");
background-size: contain;
background-position: center center;
background-repeat: no-repeat;
min-width: 90px;
min-height: 90px;
box-shadow: none;
-webkit-box-shadow: none;
}
}
#keyframes ld-vortex-out {
0% {
-webkit-transform: rotate(0deg) scale(0);
transform: rotate(0deg) scale(0);
opacity: 1;
}
60% {
-webkit-transform: rotate(1800deg) scale(1);
transform: rotate(1800deg) scale(1);
opacity: 1;
}
100% {
-webkit-transform: rotate(1800deg) scale(1);
transform: rotate(1800deg) scale(1);
opacity: 0;
}
}
#-webkit-keyframes ld-vortex-out {
0% {
-webkit-transform: rotate(0deg) scale(0);
transform: rotate(0deg) scale(0);
opacity: 1;
}
60% {
-webkit-transform: rotate(1800deg) scale(1);
transform: rotate(1800deg) scale(1);
opacity: 1;
}
100% {
-webkit-transform: rotate(1800deg) scale(1);
transform: rotate(1800deg) scale(1);
opacity: 0;
}
}
Result
Baubap loader screen
So did you check documentation?
In Ionic 3 it was a different syntax and it was not supposed to change:
https://ionicframework.com/docs/api/components/loading/LoadingController/
See their example - use different value for hiding default spinner...
Try this:
async presentLoading() {
const loading = await this.loader.create({
duration: 2000,
showBackdrop:false,
cssClass:'sa',
spinner:'hide',
message:`
<div class="custom-spinner-container">
<img class="loading" width="120px" height="120px" src="assets/loader1.gif" />
</div>`
});
return await loading.present();
}
Update: seems like in Ionic 4 suggested way to deal with loader animation is via ion-spinner. But its unclear if the old way should break or is just not supported yet in Beta

How can I bind the animation duration in Vue.js?

What I am trying to build (and not use an existing solution) is an indeterminate loader with the following template:
<template>
<div class="slider">
<div class="line" :style="getLineStyle"></div>
<div class="subline inc"></div>
<div class="subline dec"></div>
</div>
</template>
I then use a getter to add the styles for the div with the line class (which works fine).
#Prop({ default: "hsl(0, 0%, 90%)" }) private backColor!: string;
...
public get getLineStyle(): any {
return {
"background-color": "black",
position: "absolute",
opacity: "0.4",
background: this.backColor,
width: "150%",
height: "100%"
};
}
I also have the following CSS:
<style lang="scss" scoped>
.slider {
position: relative;
height: 2px;
overflow-x: hidden;
}
.subline {
position: absolute;
background: #4a8df8;
height: 100%;
}
.inc {
animation: increase 2s infinite;
}
.dec {
animation: decrease 2s 0.5s infinite;
}
#keyframes increase {
from {
left: -5%;
width: 5%;
}
to {
left: 130%;
width: 100%;
}
}
#keyframes decrease {
from {
left: -80%;
width: 80%;
}
to {
left: 110%;
width: 10%;
}
}
</style>
What I want to do is turn the .inc and .dec classes to property getters as well so that I can bind the animation duration (currently set to 2s) to a property.
I initially tried modifying the template to:
<template>
<div class="slider">
<div class="line" :style="getLineStyle"></div>
<div class="subline inc" :style="getAnimateIncreaseStyle"></div>
<div class="subline dec" :style="getAnimateDecreaseStyle"></div>
</div>
</template>
With the following getters:
public get getAnimateIncreaseStyle() {
return {
animation: "increase 2s infinite"
};
}
public get getAnimateDecreaseStyle() {
return {
animation: "decrease 2s 0.5s infinite"
};
}
Only to realise that animations cannot work when added inline.
I cannot think of any other way of doing this. Any ideas?
This is how i bind the animation duration on my progress bar in vue 3, as the previous response. It's necessary removes the scope on style
<template>
...
<div v-if="duration > 0" class="w-full bg-gray-200 -mb-1">
<div
:class="`progress-bar h-0.5 progress-bar-${themeColor}`"
:style="animation"
></div>
</div>
...
</template>
<script lang="ts">
...
props: {
duration: {
type: Number,
default: 10,
},
themeColor: {
type: String,
required: false,
default: "blue",
},
},
computed: {
animation(): string {
return `animation: ${this.duration}s linear theme-color, ${this.duration}s ease-out enter forwards`;
},
},
...
<script>
<style lang="scss">
.progress-bar {
#apply bg-gray-300;
transform-origin: right;
&.progress-bar-blue {
#apply bg-gradient-to-r from-blue-600 to-blue-300;
}
&.progress-bar-green {
#apply bg-gradient-to-r from-green-600 to-green-300;
}
&.progress-bar-yellow {
#apply bg-gradient-to-r from-yellow-600 to-yellow-300;
}
&.progress-bar-red {
#apply bg-gradient-to-r from-red-500 to-red-300;
}
}
#keyframes theme-color {
100% {
background-position: 0%;
}
0% {
background-position: 100%;
}
}
#keyframes enter {
100% {
transform: scaleX(0);
}
0% {
transform: scaleX(1);
}
}
</style>

Animate PopupMenuItem in dojo

I want to apply animation to dojo PopupMenuItem
here is code JS fiddle
Below is how i am creating popup
var pSubMenu2 = new Menu();
pSubMenu2.addChild(new MenuItem({
iconClass: "dijitEditorIcon dijitEditorIconCopy",
style: "display:inline-block"
}));
pSubMenu2.addChild(new MenuItem({
iconClass: "dijitEditorIcon dijitEditorIconCut",
style: "display:inline-block"
}));
pMenu.addChild(new PopupMenuItem({
iconClass: "dijitEditorIcon dijitEditorIconPaste",
popup: pSubMenu2
}));
You can use CSS3 animation property.
Live example here:
https://jsfiddle.net/ntkhy9q3/13/
With right to left animation:
https://jsfiddle.net/ntkhy9q3/19/
You can learn more about animation in CSS3 here:
https://developer.mozilla.org/en/docs/Web/CSS/animation
Alternative you can use JS animation, using dojo/fx, you can learn more about it at the following link:
https://dojotoolkit.org/reference-guide/1.10/dojo/fx.html
In your specific case I would suggest you using CSS3 approach.
.dijitMenuItemIconCell {
height: 40px !important;
width: 40px !important;
text-align: center !important;
-webkit-animation: fadein 2s;
/* Safari, Chrome and Opera > 12.1 */
-moz-animation: fadein 2s;
/* Firefox < 16 */
-ms-animation: fadein 2s;
/* Internet Explorer */
-o-animation: fadein 2s;
/* Opera < 12.1 */
animation: fadein 2s;
}
#keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Firefox < 16 */
#-moz-keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Safari, Chrome and Opera > 12.1 */
#-webkit-keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Internet Explorer */
#-ms-keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Opera < 12.1 */
#-o-keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}