jeary
jeary

Reputation: 3

Why is this progress bar 'flickering' when updated and how I do fix it?

I have a progress bar that I want to update whenever a user clicks on something. So it is possible to go backwards and forwards through the progress bar.

Currently, the bar seems to work, but the bar is flickering, as if the bar is being loaded every second. For eg, the user is at 70%, so the bar will fill up to there, then it clears, then it fills up to 70% again. However, this is happening hundreds of time per second, so it seems like the bar is flashing. I also dont know if what I said above is correct - I dont know if it is actually filling then clearing, filling then clearing x100. All I know is thats what it looks like, and its giving it a flickering effect.

I got the code from here: https://www.w3schools.com/howto/howto_js_progressbar.asp

and I am using the first eg, with no label.

I have amended it so that it takes an input and the bar is based on that.

function move(i) {
var elem = document.getElementById("myBar"); 
var width = 1;
var id = setInterval(frame, 10);
function frame() {
  if (width >= 100) {
    clearInterval(id);
  } else {
    width= (i/lengthOfCurrentModule)*100; 
    elem.style.width = width + '%'; 
  }
}
}

In the example it was

width++;

so I changed it to what I wanted it to do.

I tried to get rid of

  if (width >= 100) {
    clearInterval(id);
  } 

bc I thought it might have been calculating it was over 100, but the problem persists.

I dont know why its flickering like that. Any help is appreciated

Upvotes: 0

Views: 2478

Answers (3)

Joel Stevick
Joel Stevick

Reputation: 2038

I had the same problem. The progress bar was reporting progress for a compute-intensive process. I found that inserting a 500ms wait after I changed the progress value, and prior to executing the next compute-intensive step in my process, allowed the view to render smoothly.

Code snippet:

let count = 0;

for (const name of names) {
    count ++;

    this.progressLabel = name;
    this.progressValue = count / names.length;

    await sleep(500); // give a chance for the view to update

    await computeIntensiveStuff(name);
}
<ion-item>
    <ion-label position="stacked">
        Adding: {{progressLabel}}
    </ion-label>

    <ion-progress-bar [value]="progressValue">
    </ion-progress-bar>
</ion-item>

Upvotes: 0

Niet the Dark Absol
Niet the Dark Absol

Reputation: 324690

Broadly speaking, if you can use CSS to animate something, then you should. This allows the browser to fine-tune control, accounting for things like mobile device computing power, battery and so on. This also automatically includes things like delta-timing to ensure that the animation takes the correct amount of time no matter what.

function move() {
  var elem = document.getElementById("myBar");
  var perc = +document.getElementById("percentage").value;
  
  // optional: ensures the bar fills/empties at the same rate by varying the animation duration
  var previous = move.previous || 0;
  move.previous = perc;
  var change = Math.abs(perc - previous);
  elem.style.transitionDuration = (change*10)+"ms";
  
  elem.style.width = perc+"%";
}
#myProgress {
  width: 100%;
  background-color: grey;
  overflow: hidden;
}

#myBar {
  width: 0%;
  height: 30px;
  background-color: green;
  transition: width 500ms linear;
}
<div id="myProgress">
  <div id="myBar"></div>
</div>
<input type="number" min="0" max="100" id="percentage">
<button onclick="move()">Click Me</button>

Upvotes: 1

Aaron
Aaron

Reputation: 1737

Is this what you wanted to achieve? You can enter a value and the progressbar fills up to that value.no logic implemented so please enter a value between 1 and 100 and click the button.

function move() {
  var elem = document.getElementById("myBar");
  var perc = document.getElementById("percentage").value;
 
  var width = 1;
  var id = setInterval(frame, 10);
  function frame() {
    if (width >= perc) {
      clearInterval(id);
    } else {
      width++; 
      elem.style.width = width + '%'; 
    }
  }
}
#myProgress {
  width: 100%;
  background-color: grey;
}

#myBar {
  width: 1%;
  height: 30px;
  background-color: green;
}
<div id="myProgress">
  <div id="myBar"></div>
</div>
<input type="number" id="percentage">
<button onclick="move()">Click Me</button>

Upvotes: 0

Related Questions