Reputation: 123
I have this round progress bar that shows the progress of completed tasks. On progress change, the bar increases/decreases over 0.5s. The bar itself is made out of 2 halves, so in my JS I had to add some extra functions to delay and change the transition time if, for example, you would have an uneven number of total tasks.
Now, this all works just fine, until I "reconstruct" the progress bar (clicking the "reload" button) by just emptying the bar wrapper and appending all the divs and necessary data to re-display the bar with its current progress. At this point, whenever the progress bar hits the midpoint, for some reason, the transition isn't smooth as prior to "reload", but if you refresh the page again, the transition (at midpoint) is all fine. I have no clue why this happens...
Here's the JSFiddle
UPDATE In the "on reload" in JS, I forgot to re-initialize "bar_transition = $('.circle .bar_transition .sub-progress')"
function updateSubtaskProgressBar(subs_completed, total_subs, progress_bar_transition, toggle, mod, reload_btn) {
var left_side = $(".sub-progress-bar_transition .circle .left .sub-progress");
var right_side = $(".sub-progress-bar_transition .circle .right .sub-progress");
progress = subs_completed / total_subs * 360;
transition = 500;
delay = transition / 2;
rot_reminder = 0;
if (progress < 180) {
rot_right = 0;
right_side.css({
'transform': 'rotate(' + rot_right + 'deg)'
});
rot_left = progress
rot_reminder = 180 - rot_left
if (rot_reminder != 0 && mod != 0 && toggle == 0) {
progress_bar_transition.css({
'transition': 'all ' + delay / 1000 + 's ease-in'
});
setTimeout(function () {
progress_bar_transition.css({
'transition': 'all ' + delay / 1000 + 's ease-out'
});
left_side.css({
'transform': 'rotate(' + rot_left + 'deg)'
});
}, delay);
toggle = 1 - toggle
reload_btn.data('toggle', toggle)
} else {
progress_bar_transition.css({
'transition': 'all ' + transition / 1000 + 's ease-in-out'
});
left_side.css({
'transform': 'rotate(' + rot_left + 'deg)'
});
}
} else {
rot_left = 180;
left_side.css({
'transform': 'rotate(' + rot_left + 'deg)'
});
rot_right = progress - 180;
rot_reminder = rot_right
if (rot_reminder != 0 && mod != 0 && toggle == 1) {
progress_bar_transition.css({
'transition': 'all ' + delay / 1000 + 's ease-in'
});
setTimeout(function () {
progress_bar_transition.css({
'transition': 'all ' + delay / 1000 + 's ease-out'
});
right_side.css({
'transform': 'rotate(' + rot_right + 'deg)'
});
}, delay);
toggle = 1 - toggle
reload_btn.data('toggle', toggle)
} else {
progress_bar_transition.css({
'transition': 'all ' + transition / 1000 + 's ease-in-out'
});
right_side.css({
'transform': 'rotate(' + rot_right + 'deg)'
});
}
}
}
function setSubtaskProgressBar(subs_completed, total_subs, bar_transition) {
modulo = 0;
current_progress = 0;
var left_side = $(".sub-progress-bar_transition .circle .left .sub-progress");
var right_side = $(".sub-progress-bar_transition .circle .right .sub-progress");
modulo = total_subs%2
current_progress = subs_completed / total_subs * 360;
var reload = $('.reload')
reload.data('completed', subs_completed)
reload.data('total', total_subs)
reload.data('modulo', modulo)
if (current_progress < 180) {
rot_left = current_progress
rot_right = 0
left_side.css({
'transform': 'rotate(' + rot_left + 'deg)'
});
reload.data('toggle', 1)
} else {
rot_left = 180
rot_right = current_progress - 180
left_side.css({
'transform': 'rotate(' + rot_left + 'deg)'
});
right_side.css({
'transform': 'rotate(' + rot_right + 'deg)'
});
reload.data('toggle', 0)
}
bar_transition.css({
'transition': 'none'
});
}
$(document).ready(function () {
subs_completed = 3;
total_subs = 5;
bar_transition = $('.circle .bar_transition .sub-progress')
number = $('.number')
number.html(subs_completed + '/' + total_subs)
setSubtaskProgressBar(subs_completed, total_subs, bar_transition)
$(document).on('click', '.add', function () {
subs_completed += 1
$('.number').html(subs_completed + '/' + total_subs)
reload = $('.reload')
reload.data('completed', subs_completed)
modulo = reload.data('modulo')
toggle = reload.data('toggle')
total = reload.data('total')
updateSubtaskProgressBar(subs_completed, total, bar_transition, toggle, modulo, reload)
})
$(document).on('click', '.remove', function () {
subs_completed -= 1;
$('.number').html(subs_completed + '/' + total_subs)
reload = $('.reload')
reload.data('completed', subs_completed)
modulo = reload.data('modulo')
toggle = reload.data('toggle')
total = reload.data('total')
updateSubtaskProgressBar(subs_completed, total, bar_transition, toggle, modulo, reload)
})
$(document).on('click', '.reload', function () {
num = $(this).data('completed') + '/' + $(this).data('total')
data = '<div class="subtask-circular-progress sub-progress-bar_transition" data-completed="'+$(this).data('completed')+'" data-total="'+$(this).data('total')+'" data-modulo="'+$(this).data('modulo')+'" data-toggle="'+$(this).data('toggle')+'"><div class="inner"></div><div class="number">'+num+'</div><div class="circle"><div class="bar_transition left"><div class="sub-progress"></div></div><div class="bar_transition right"><div class="sub-progress"></div></div></div></div>'
wrapper = $('.wrapper').empty();
wrapper.append(data)
setSubtaskProgressBar(subs_completed, total_subs, bar_transition)
console.log('reload')
})
});
body{
background-color: #333;
}
.subtask-circular-progress {
position: absolute;
left: 50%;
top: 40%;
height: 100px;
width: 100px;
background-color: red;
}
.subtask-circular-progress .inner {
position: absolute;
z-index: 6;
top: 50%;
left: 50%;
height: 80px;
width: 80px;
margin: -40px 0 0 -40px;
border-radius: 100%;
background: #454545;
}
.subtask-circular-progress .number {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 10;
font-size: 15px;
font-weight: 500;
color: white;
}
.subtask-circular-progress .bar_transition {
position: absolute;
height: 100%;
width: 100%;
background: #fff;
-webkit-border-radius: 100%;
border-radius: 100%;
clip: rect(0px, 100px, 100px, 50px);
}
.circle .bar_transition .sub-progress {
position: absolute;
height: 100%;
width: 100%;
-webkit-border-radius: 100%;
border-radius: 100%;
clip: rect(0px, 50px, 100px, 0px);
background: #4158d0;
transition: all 0.5s ease-in-out;
}
.circle .left .sub-progress {
transform: rotate(0deg);
}
.circle .right {
transform: rotate(180deg);
z-index: 3;
}
.circle .right .sub-progress {
transform: rotate(0deg);
}
.buttons{
position: absolute;
left: 50%;
top: 60%;
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<div class="subtask-circular-progress sub-progress-bar_transition">
<div class="inner"></div>
<div class="number">100%</div>
<div class="circle">
<div class="bar_transition left">
<div class="sub-progress"></div>
</div>
<div class="bar_transition right">
<div class="sub-progress"></div>
</div>
</div>
</div>
</div>
<div class="d-flex buttons">
<button type="button" class="btn btn-success add">+</button>
<button type="button" class="btn btn-success remove ms-4">-</button>
<button type="button" class="btn btn-success reload ms-4" data-completed="" data-total="" data-modulo="" data-toggle="">reload</button>
</div>
Upvotes: 1
Views: 805
Reputation: 3559
The issue was tricky to find, but you are referring to the bar_transition
global variable after that the relative content of the DOM is deleted.
After the DOM replacement, the content of bar_transition
does not reflect the DOM anymore, is lost.
You need to manually update the content of the variable is the reload callback:
bar_transition = $('.circle .bar_transition .sub-progress');
function updateSubtaskProgressBar(subs_completed, total_subs, progress_bar_transition, toggle, mod, reload_btn) {
var left_side = $(".sub-progress-bar_transition .circle .left .sub-progress");
var right_side = $(".sub-progress-bar_transition .circle .right .sub-progress");
progress = subs_completed / total_subs * 360;
transition = 500;
delay = transition / 2;
rot_reminder = 0;
if (progress < 180) {
rot_right = 0;
right_side.css({
'transform': 'rotate(' + rot_right + 'deg)'
});
rot_left = progress
rot_reminder = 180 - rot_left
if (rot_reminder != 0 && mod != 0 && toggle == 0) {
progress_bar_transition.css({
'transition': 'all ' + delay / 1000 + 's ease-in'
});
setTimeout(function () {
progress_bar_transition.css({
'transition': 'all ' + delay / 1000 + 's ease-out'
});
left_side.css({
'transform': 'rotate(' + rot_left + 'deg)'
});
}, delay);
toggle = 1 - toggle
reload_btn.data('toggle', toggle)
} else {
progress_bar_transition.css({
'transition': 'all ' + transition / 1000 + 's ease-in-out'
});
left_side.css({
'transform': 'rotate(' + rot_left + 'deg)'
});
}
} else {
rot_left = 180;
left_side.css({
'transform': 'rotate(' + rot_left + 'deg)'
});
rot_right = progress - 180;
rot_reminder = rot_right
if (rot_reminder != 0 && mod != 0 && toggle == 1) {
progress_bar_transition.css({
'transition': 'all ' + delay / 1000 + 's ease-in'
});
setTimeout(function () {
progress_bar_transition.css({
'transition': 'all ' + delay / 1000 + 's ease-out'
});
right_side.css({
'transform': 'rotate(' + rot_right + 'deg)'
});
}, delay);
toggle = 1 - toggle
reload_btn.data('toggle', toggle)
} else {
progress_bar_transition.css({
'transition': 'all ' + transition / 1000 + 's ease-in-out'
});
right_side.css({
'transform': 'rotate(' + rot_right + 'deg)'
});
}
}
}
function setSubtaskProgressBar(subs_completed, total_subs, bar_transition) {
modulo = 0;
current_progress = 0;
var left_side = $(".sub-progress-bar_transition .circle .left .sub-progress");
var right_side = $(".sub-progress-bar_transition .circle .right .sub-progress");
modulo = total_subs%2
current_progress = subs_completed / total_subs * 360;
var reload = $('.reload')
reload.data('completed', subs_completed)
reload.data('total', total_subs)
reload.data('modulo', modulo)
if (current_progress < 180) {
rot_left = current_progress
rot_right = 0
left_side.css({
'transform': 'rotate(' + rot_left + 'deg)'
});
reload.data('toggle', 1)
} else {
rot_left = 180
rot_right = current_progress - 180
left_side.css({
'transform': 'rotate(' + rot_left + 'deg)'
});
right_side.css({
'transform': 'rotate(' + rot_right + 'deg)'
});
reload.data('toggle', 0)
}
bar_transition.css({
'transition': 'none'
});
}
$(document).ready(function () {
subs_completed = 3;
total_subs = 5;
bar_transition = $('.circle .bar_transition .sub-progress')
number = $('.number')
number.html(subs_completed + '/' + total_subs)
setSubtaskProgressBar(subs_completed, total_subs, bar_transition)
$(document).on('click', '.add', function () {
subs_completed += 1
$('.number').html(subs_completed + '/' + total_subs)
reload = $('.reload')
reload.data('completed', subs_completed)
modulo = reload.data('modulo')
toggle = reload.data('toggle')
total = reload.data('total')
updateSubtaskProgressBar(subs_completed, total, bar_transition, toggle, modulo, reload)
})
$(document).on('click', '.remove', function () {
subs_completed -= 1;
$('.number').html(subs_completed + '/' + total_subs)
reload = $('.reload')
reload.data('completed', subs_completed)
modulo = reload.data('modulo')
toggle = reload.data('toggle')
total = reload.data('total')
updateSubtaskProgressBar(subs_completed, total, bar_transition, toggle, modulo, reload)
})
$(document).on('click', '.reload', function () {
num = $(this).data('completed') + '/' + $(this).data('total')
data = '<div class="subtask-circular-progress sub-progress-bar_transition" data-completed="'+$(this).data('completed')+'" data-total="'+$(this).data('total')+'" data-modulo="'+$(this).data('modulo')+'" data-toggle="'+$(this).data('toggle')+'"><div class="inner"></div><div class="number">'+num+'</div><div class="circle"><div class="bar_transition left"><div class="sub-progress"></div></div><div class="bar_transition right"><div class="sub-progress"></div></div></div></div>'
wrapper = $('.wrapper').empty();
wrapper.append(data)
// Fix is here!
bar_transition = $('.circle .bar_transition .sub-progress');
setSubtaskProgressBar(subs_completed, total_subs, bar_transition)
console.log('reload')
})
});
body{
background-color: #333;
}
.subtask-circular-progress {
position: absolute;
left: 50%;
top: 40%;
height: 100px;
width: 100px;
background-color: red;
}
.subtask-circular-progress .inner {
position: absolute;
z-index: 6;
top: 50%;
left: 50%;
height: 80px;
width: 80px;
margin: -40px 0 0 -40px;
border-radius: 100%;
background: #454545;
}
.subtask-circular-progress .number {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 10;
font-size: 15px;
font-weight: 500;
color: white;
}
.subtask-circular-progress .bar_transition {
position: absolute;
height: 100%;
width: 100%;
background: #fff;
-webkit-border-radius: 100%;
border-radius: 100%;
clip: rect(0px, 100px, 100px, 50px);
}
.circle .bar_transition .sub-progress {
position: absolute;
height: 100%;
width: 100%;
-webkit-border-radius: 100%;
border-radius: 100%;
clip: rect(0px, 50px, 100px, 0px);
background: #4158d0;
transition: all 0.5s ease-in-out;
}
.circle .left .sub-progress {
transform: rotate(0deg);
}
.circle .right {
transform: rotate(180deg);
z-index: 3;
}
.circle .right .sub-progress {
transform: rotate(0deg);
}
.buttons{
position: absolute;
left: 50%;
top: 60%;
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<div class="subtask-circular-progress sub-progress-bar_transition">
<div class="inner"></div>
<div class="number">100%</div>
<div class="circle">
<div class="bar_transition left">
<div class="sub-progress"></div>
</div>
<div class="bar_transition right">
<div class="sub-progress"></div>
</div>
</div>
</div>
</div>
<div class="d-flex buttons">
<button type="button" class="btn btn-success add">+</button>
<button type="button" class="btn btn-success remove ms-4">-</button>
<button type="button" class="btn btn-success reload ms-4" data-completed="" data-total="" data-modulo="" data-toggle="">reload</button>
</div>
Upvotes: 1