<CANVAS> Spinner Revisited
by webdood on Jul.11, 2012, under Canvas, Javascript, Software Development
I previously invented a Javascript-only, CANVAS-based spinner. I went to re-use this code today and found it to be less than easy to use.
Therefore, I rejiggered a few things to make it so you can create an number of spinners on page, with each spinner having its own start, stop, display and toggle method exposed.
function Spinner( oHTMLElement, params ) { if (typeof(oHTMLElement)=="string") { oHTMLElement = document.getElementById(oHTMLElement); } if (oHTMLElement) { if (params===undefined) { params={} }; var oCanvas = document.createElement('canvas'), context = null, height = parseFloat( getComputedStyle( oHTMLElement, null)["height"] ), width = parseFloat( getComputedStyle( oHTMLElement, null)["width"] ), radius = Math.min(height / 2, width / 2), innerRadius = params["innerRadius"] || radius * 2 * .27833333, outerRadius = params["outerRadius"] || radius * .99, finWidth = params["finWidth"] || .08 * radius, finColors = params["finColors"] || [ "e8e8e8","f1f1f1", "fafafa", "b2b2b2", "b6b6b6", "b9b9b9", "bebebe", "c3c3c3", "c9c9c9", "d0d0d0", "d7d7d7", "dfdfdf" ], strokeStyle = params["strokeStyle"] || "rgba(128,128,128,1)", strokeWidth = (params["strokeWidth"]!==undefined) ? params["strokeWidth"] : 2, // Specifies whether an outline will appear around each fin finColorOffset = 0, // This is a counter that is mod-ed around 12 to draw the spinner with appropriate color as indexed into the finColors array spinnerInterval = null; // Handle to setInterval operation generating spin animation // Set up the <canvas> object oCanvas.width = width; oCanvas.height = height; context = oCanvas.getContext('2d'); context.translate( radius, radius ); oHTMLElement.appendChild( oCanvas ); draw(); } /////////////////////////////////////////////////////////////////////////////////// // Spinner.display(boolean bDisplay) - show/hides the parent oHTMLElement // // ================================= (external method) // /////////////////////////////////////////////////////////////////////////////////// this.display = function( bDisplay ) { if ( bDisplay ) { oHTMLElement.style.display = 'block'; } else { oHTMLElement.style.display = 'none'; } } /////////////////////////////////////////////////////////////////////////////////// // draw() - this clears the previous spinner drawn, then loops through the // // ====== 12 fins, rotating the canvas 30 degrees each time and drawing each // // fin with the appropriate color from the finColors array (internal method) // /////////////////////////////////////////////////////////////////////////////////// function draw() { context.clearRect(-width,-height,width*2,height*2); for (var i=0;i<12;i++) { drawFin( finColors[ (i + finColorOffset) % 12] ); context.rotate(-360/12 * Math.PI/180); } } /////////////////////////////////////////////////////////////////////////////////// // drawFin( string fillColor ) - this draws a single fin. Each is made up of a // // ========================== half circle on either end of a rectangle. // // Trust me, this took a while to work out. But I overcame! (internal method) // /////////////////////////////////////////////////////////////////////////////////// function drawFin( fillColor ) { var ctx = context; ctx.fillStyle = fillColor; ctx.strokeStyle = strokeStyle; ctx.lineWidth = strokeWidth; ctx.beginPath(); ctx.arc(outerRadius-finWidth,0,finWidth,-Math.PI/2,Math.PI/2, false); ctx.rect(innerRadius,-finWidth,outerRadius-innerRadius-finWidth,finWidth*2); ctx.arc(innerRadius,0,finWidth,Math.PI/2,-Math.PI/2,false); ctx.closePath(); if (strokeWidth > 0) { ctx.stroke(); } ctx.fill(); } /////////////////////////////////////////////////////////////////////////////////// // Spinner.start() - sets up an interval that continues to call spin(). // // =============== (external method) // /////////////////////////////////////////////////////////////////////////////////// this.start = function() { this.display( true ); spinnerInterval = setInterval( function() { spin(); }, 100); } /////////////////////////////////////////////////////////////////////////////////// // Spinner.stop() - cancels the interval used to continuously call spin(). // // ============== (external method) // /////////////////////////////////////////////////////////////////////////////////// this.stop = function() { clearInterval( spinnerInterval ); spinnerInterval = null; } /////////////////////////////////////////////////////////////////////////////////// // spin() - this increments the offset into the fin color array. Really, the // // ====== spinner is not "spinning", per se, but rather re-drawing the fins // // in-place with a set of continuously changing colors. (internal method) // /////////////////////////////////////////////////////////////////////////////////// function spin() { finColorOffset += 1; draw(); } this.toggle = function() { if (spinnerInterval === null) { this.start(); } else { this.stop(); } } }
Please give credit when you steal this!
by Shannon Norrell, 2010-2012