A canvas showing loading progress in a circle. Here it's faked and animated on requestAnimationFrame. But you get the idea.
Created
December 30, 2014 19:47
-
-
Save reportbase/019435fe36374eb0f068 to your computer and use it in GitHub Desktop.
Circular canvas loader
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
<h1>Circular canvas loader</h1> | |
<div class="loader-holder" id="loader-holder"> | |
<div class="percent"></div> | |
<canvas id="loader"></canvas> | |
</div> | |
<button id="btn-reload">Do it!</button> |
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
;(function () { | |
// request animation frame | |
window.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(e){window.setTimeout(e,1e3/60)}}() | |
var Loader = function (options) { | |
this.options = options; | |
this.options.completeCallback = this.options.completeCallback || function () {}; | |
this.options.progressCallback = this.options.progressCallback || function () {}; | |
this.options.borderColor = options.borderColor || '#0000000'; | |
this.canvas = document.querySelector(options.canvas); | |
this.ctx = this.canvas.getContext('2d'); | |
this.loaded = 0; | |
var parent = this.canvas.parentNode; | |
this.canvas.width = parent.offsetWidth; | |
this.canvas.height = parent.offsetHeight; | |
this.canvasR = parent.offsetWidth >> 1; | |
this.draw(); | |
} | |
Loader.prototype.init = function() { | |
this.loaded = 0; | |
this.load(); | |
} | |
Loader.prototype.load = function() { | |
var me = this; | |
me.draw(); | |
me.options.progressCallback(me.loaded); | |
if (me.loaded < 100) { | |
requestAnimFrame(function () { | |
me.load(); | |
}); | |
} else { | |
me.loadingComplete(); | |
} | |
me.loaded += .5; | |
} | |
Loader.prototype.loadingComplete = function() { | |
this.options.completeCallback(); | |
} | |
Loader.prototype.draw = function () { | |
var fillRadian = 360 / 100 * this.loaded * Math.PI / 180, | |
midX = this.canvas.width * .5, | |
midY = this.canvas.height * .5; | |
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); | |
// draw arc | |
this.ctx.beginPath(); | |
this.ctx.arc(midX, midY, this.canvasR, 0, fillRadian, false); | |
this.ctx.lineWidth = this.options.arcWidth, | |
this.ctx.strokeStyle = this.options.arcColor, | |
this.ctx.stroke(); | |
// draw border | |
if (this.options.borderWidth !== 'undefined') { | |
this.ctx.beginPath(); | |
this.ctx.arc(midX, midY, this.canvasR, 0, Math.PI * 2, false); | |
this.ctx.arc(midX, midY, this.canvasR - this.options.borderWidth, 0, Math.PI * 2, true); | |
this.ctx.fillStyle = this.options.borderColor, | |
this.ctx.fill(); | |
} | |
} | |
var holder = document.getElementById('loader-holder'); | |
var loadingProgress = function (percent) { | |
var percentHolder = document.querySelector('.percent'); | |
percentHolder.innerHTML = Math.round(percent) + '%'; | |
} | |
var loadingDone = function () { | |
holder.classList.add('loading-done'); | |
} | |
var loader = new Loader({ | |
canvas: '#loader', | |
arcWidth: 100, | |
arcColor: 'rgb(0, 165, 255)', | |
borderWidth: 20, | |
borderColor: 'rgb(53, 138, 185)', | |
progressCallback: loadingProgress, | |
completeCallback: loadingDone | |
}); | |
var button = document.getElementById('btn-reload'); | |
button.addEventListener('mousedown', function() { | |
holder.classList.remove('loading-done'); | |
loader.init(); | |
}, false); | |
})(); |
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
@import "bourbon"; | |
@import url(http://fonts.googleapis.com/css?family=Roboto:700,300); | |
$radius: 200px; | |
* { | |
box-sizing: border-box; | |
} | |
body { | |
font-family: 'Roboto', sans-serif; | |
font-weight: 300; | |
padding: 2em; | |
text-align: center; | |
} | |
h1 { | |
font-size: 1.5em; | |
} | |
button { | |
$bg: rgb(0, 165, 255); | |
background: $bg; | |
border: none; | |
color: #fff; | |
padding: 10px 15px; | |
border-radius: 10px; | |
cursor: pointer; | |
@include transition(background .1s ease-in); | |
&:hover { | |
background: darken($bg, 20%); | |
} | |
} | |
.loader-holder { | |
width: $radius; | |
height: $radius; | |
position: relative; | |
margin: 30px auto; | |
&.loading-done { | |
@include animation(loading-done .5s cubic-bezier(.99, .27, .99, 1.01) forwards); | |
.percent { | |
opacity: 0; | |
} | |
} | |
.percent { | |
position: absolute; | |
z-index: 10; | |
text-align: center; | |
width: 100%; | |
top: 50%; | |
font-weight: 700; | |
font-size: 1.5em; | |
line-height: 0; | |
color: rgb(38, 38, 38); | |
opacity: 1; | |
@include transition(opacity .2s ease-out); | |
.loading-done & { | |
// update sass | |
} | |
} | |
& > canvas { | |
width: 100%; | |
height: 100%; | |
border-radius: 100%; | |
} | |
} | |
@include keyframes(loading-done) { | |
0% { | |
@include transform(scale(1)); | |
} | |
20% { | |
@include transform(scale(1.2)); | |
} | |
100% { | |
@include transform(scale(0)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment