Reputation: 6996
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?
Upvotes: 2
Views: 2277
Reputation: 141
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>
Upvotes: 1