I am working on a project that involves creating a list of data and using a template to draw blocks with time bars for each item in the list.
The order of the items in the list can be updated at any time. However, I have noticed that whenever the list order is updated, some of the time bar animations are unexpectedly restarted.
I have created a jsFiddle to simulate this behavior. Can someone please suggest a solution to prevent this issue from happening?
JsFiddle Code:
https://jsfiddle.net/tklfiddle/30z4km8f/7/
Here is the Vue Template:
<div id="app">
<h2>TimeBars:</h2>
<button @click="reOrder">
Shuffle
</button>
<ul class="listWrapper">
<li v-for="(item, index) in list" class="row itemTest" :id="item.id" :key="item.id">
<div class="timeBarContainer">
<div class="timeBar" :style="{animationDuration: item.duration+ 's'}">
</div>
<div class="timeBarText">
{{item.id}}
</div>
</div>
</li>
</ul>
{{list}}
</div>
JavaScript:
new Vue({
el: "#app",
data: {
list: [
{ id: "bar1", done: false, duration: 10 },
{ id: "bar2", done: false, duration: 10 },
{ id: "bar3", done: true, duration: 10 },
{ id: "bar4", done: true, duration: 10 }
]
},
mounted(){
console.log("DEBUG: mounted", $("body"));
$(".listWrapper").on('DOMNodeRemoved', function(e) {
console.log(e.target, ' was removed');
});
},
methods: {
reOrder: function(){
this.list = shuffle(this.list);
//this.list.pop();
console.log("DEBUG: this.list:", JSON.stringify(this.list));
function shuffle(array) {
var currentIndex = array.length, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return JSON.parse(JSON.stringify(array));
}
}
}
})
CSS:
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
>div{
display: inline-block;
}
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
.timeBarContainer{
width: 100%;
height: 15px;
position: relative;
}
.timeBar{
width: 100%;
height: 100%;
background-color: red;
float: right;
animation: timeBarAnimation 0s linear normal forwards;
}
.timeBarText{
position: absolute;
}
@keyframes timeBarAnimation {
0% {
width: 100%;
}
100% {
width: 0;
}
}
CodeSandBox Code:
If you want to see another example coded with CodeSandbox, check out this one. You will notice that the TimeBar component doesn't get unmounted after being shuffled, but the CSS animation restarts unexpectedly.
https://codesandbox.io/s/great-smoke-n806b?file=/src/components/TimeBar.vue