JSFiddle - React, Tailwind, and code Playground
by Atinux
HTML
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<script src="https://unpkg.com/[email protected]"></script>
<div id="app">
<ul>
<li v-for="(index, item) in list" class="goal" :key="index" transition="bounce">
<img :src="`http://lorempixel.com/100/150/abstract/?_=`+index">
<h3>{{ item.name }}</h3>
<animated-line :item="item"></animated-line>
</li>
</ul>
</div>
CSS
.goal {
list-style-type: none;
border: 1px #ddd solid;
background: white;
padding: 20px;
float: left;
}
img {
width: 100px;
height: 150px;
}
.line {
width: 100%;
height: 5px;
}
.line-percent {
background: #1c90f3;
height: 100%;
}
.bounce-enter-active {
animation: bounce-in .5s;
}
.bounce-leave-active {
animation: bounce-out .5s;
}
@keyframes bounce-in {
0% {
transform: scale(0.5);
}
50% {
transform: scale(1.2);
}
100% {
transform: scale(1);
}
}
@keyframes bounce-out {
0% {
transform: scale(1);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(0);
}
}
JavaScript
Vue.component('animated-line', {
template: `<div class="line">
<div class="line-percent" :style="{ 'width' : animatedWidth }"></div>
</div>`,
props: ['item'],
data: function () {
return { animatedWidth: 0 };
},
ready: function () {
var vm = this
var widthTo = (vm.item.badge_progress / vm.item.badge_goal) * 100;
function animate (time) {
requestAnimationFrame(animate)
TWEEN.update(time)
}
setTimeout(function () {
new TWEEN.Tween({ tweeningNumber: vm.animatedWidth })
.easing(TWEEN.Easing.Quadratic.Out)
.to({ tweeningNumber: widthTo }, 1000)
.onUpdate(function () {
vm.animatedWidth = this.tweeningNumber.toFixed(0) + '%'
console.log(vm.animatedWidth);
})
.start()
animate();
}, 500);
}
})
new Vue({
el: '#app',
data: {
list: [{
name: 'Name #1',
badge_progress: 30,
badge_goal: 100
}, {
name: 'Name #2',
badge_progress: 50,
badge_goal: 100
}, {
name: 'Name #3',
badge_progress: 90,
badge_goal: 100
}]
}
})