-
-
Save kangax/1051534 to your computer and use it in GitHub Desktop.
Progressify - a progress bar approximator for smoothness
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Progressify</title> | |
<script> | |
var Plot = (function() { | |
function Point(duration, progress) { | |
this.duration = duration; | |
this.progress = progress; | |
} | |
function Plot() { | |
this.points = [ ]; | |
this.prevProgress = 0; | |
} | |
Plot.prototype.STARTING_SLOPE = 4; | |
Plot.prototype.addPoint = function(duration, progress) { | |
if (this.actualProgressIncreased(progress)) { | |
this.points.push(new Point(duration, progress)); | |
} | |
}; | |
Plot.prototype.progressAt = function(duration) { | |
var newProgress; | |
if (this.points.length !== 0 && this.points[this.points.length - 1].progress >= 100) { | |
newProgress = 100; | |
} | |
else { | |
newProgress = this.calcProgress(duration); | |
} | |
newProgress = Math.max(this.prevProgress, Math.round(newProgress)); | |
this.prevProgress = newProgress; | |
return newProgress; | |
}; | |
Plot.prototype.calcProgress = function(duration) { | |
return Math.min(99, (duration * this.averageSlope())); | |
}; | |
Plot.prototype.actualProgressIncreased = function(progress) { | |
var prevProgress = this.points[this.points.length - 1] | |
? this.points[this.points.length - 1].progress | |
: 0; | |
return progress > prevProgress; | |
}; | |
Plot.prototype.slopes = function() { | |
var slopes = [this.STARTING_SLOPE]; | |
for (var i = 0, len = this.points.length; i < len; i++) { | |
var point = this.points[i]; | |
var prevDuration = (i == 0 ? 0 : this.points[i - 1].duration); | |
var prevProgress = (i == 0 ? 0 : this.points[i - 1].progress); | |
slopes.push((point.progress - prevProgress) / (point.duration - prevDuration)) | |
} | |
return slopes; | |
}; | |
Plot.prototype.averageSlope = function() { | |
var sum = 0; | |
for (var i = 0, slopes = this.slopes(), len = slopes.length; i < len; i++) { | |
sum += slopes[i]; | |
} | |
return sum / slopes.length; | |
}; | |
return Plot; | |
})(); | |
</script> | |
</head> | |
<body> | |
<progress value="0" max="100"></progress> | |
<script> | |
var sample1 = [ [2, 9 ], | |
[5, 50 ], | |
[5, 75 ], | |
[3, 100 ] ]; | |
var sample2 = [ [5, 15 ], | |
[2, 30 ], | |
[4, 45 ], | |
[3, 65 ], | |
[6, 100 ] ] | |
var sample3 = [ [1, 1 ], | |
[5, 50 ], | |
[5, 100 ] ]; | |
var sample4 = [ [1, 0 ], | |
[10, 25 ], | |
[2, 100 ] ]; | |
var sample = sample4; | |
var plot = new Plot(); | |
var pollingDuration = 0; | |
var progressEl = document.getElementsByTagName('progress')[0]; | |
function fetchFromSample() { | |
var pair = sample.shift(); | |
var interval = pair[0]; | |
var progress = pair[1]; | |
setTimeout(function() { | |
pollingDuration += interval; | |
plot.addPoint(pollingDuration, progress); | |
if (sample.length > 0) { | |
fetchFromSample(); | |
} | |
}, interval * 1000); | |
} | |
var startTime = new Date(); | |
fetchFromSample(); | |
var interval = setInterval(function() { | |
var value = plot.progressAt((new Date - startTime) / 1000); | |
if (value === 100) { | |
clearInterval(interval); | |
} | |
progressEl.value = value; | |
}, 100); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment