Skip to content

Instantly share code, notes, and snippets.

@jsturgis
Last active December 14, 2015 17:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jsturgis/5122359 to your computer and use it in GitHub Desktop.
Save jsturgis/5122359 to your computer and use it in GitHub Desktop.
Draw a clock to canvas and with support for HiDPI screens.
/*jshint forin:true, noarg:true, noempty:true, eqeqeq:true, bitwise:true, undef:true, unused:true, curly:true, browser:true, jquery:true, indent:4, maxerr:50, maxparams:4, maxdepth:3, maxcomplexity:3, white: false */
/*global window: true*/
/* params: min=0-59 time offset, clock: node containing the clock, clockColor: color of the clock */
window.canvasClock = function ( min, clock, clockColor ) {
// setup clock
var canvas = clock.getElementsByTagName('canvas')[0],
c2d = canvas.getContext('2d'),
mins = 0,
hour = 0,
width = canvas.width,
height = canvas.height,
halfWidth = width / 2,
halfHeight = width / 2,
lineColor = clockColor || '#000',
linewidth = 1,
auto = true,
devicePixelRatio = window.devicePixelRatio || 1,
backingStoreRatio = c2d.webkitBackingStorePixelRatio ||
c2d.mozBackingStorePixelRatio ||
c2d.msBackingStorePixelRatio ||
c2d.oBackingStorePixelRatio ||
c2d.backingStorePixelRatio || 1,
ratio = devicePixelRatio / backingStoreRatio;
// upscale the canvas if the two ratios don't match
if (auto && devicePixelRatio !== backingStoreRatio) {
canvas.width = width * ratio;
canvas.height = height * ratio;
canvas.style.width = width + 'px';
canvas.style.height = height + 'px';
// now scale the context to counter
// the fact that we've manually scaled
// our canvas element
c2d.scale(ratio, ratio);
}
function updateTime(){
var currentDate = new Date(),
currentHrs = currentDate.getHours(),
currentMins = currentDate.getMinutes();
// handle hour boundaries
if(min > currentMins){
mins = min - currentMins;
mins = 60 - mins;
hour = currentHrs - 1;
}else{
hour = currentHrs;
mins = currentMins - min;
}
}
function setOffset(offset){
min = offset;
}
function hourPos(){
return Math.PI/6*(hour+(mins/60));
}
function minutePos(){
return Math.PI/30*(mins);
}
this.getOffset = function(){
return min;
};
this.draw = function(offset){
if(offset){
setOffset(offset);
}
// update time
updateTime();
c2d.clearRect(0,0,height,width);
c2d.lineWidth=linewidth;
c2d.save();
// draw clock face
c2d.restore();
c2d.strokeStyle=lineColor;
c2d.fillStyle=lineColor;
c2d.beginPath();
// half the width, 3rd val is half width - 2*linewidth
c2d.arc(halfHeight,halfWidth,(halfWidth - (2 * linewidth)),0,Math.PI*2,true);
c2d.stroke();
c2d.save();
// only draw the middle dot for larger devices
if(height >= 30){
// draw the middle dot
c2d.beginPath();
c2d.arc(halfWidth, halfHeight, 2, 0, Math.PI*2, true);
c2d.fill();
c2d.save();
}
// half the width
c2d.translate(halfWidth,halfHeight);
// setup line styles
c2d.strokeStyle=lineColor;
c2d.save();
//Draw clock pointers but this time rotate the canvas rather than
//calculate x/y start/end positions.
//Draw hour hand
c2d.rotate(hourPos());
c2d.beginPath();
c2d.moveTo(0,1);
c2d.lineTo(0,-(halfWidth - (2 * linewidth)) + 4);
c2d.stroke();
c2d.restore();
c2d.save();
//Draw minute hand
c2d.rotate(minutePos());
c2d.beginPath();
// bottom end of arm always 0, 0
c2d.moveTo(0,0);
// top end of arm -length of arm max half width - linewidth
c2d.lineTo(0,-(halfWidth - (2 * linewidth)) + 3);
c2d.stroke();
c2d.restore();
//Additional restore to go back to state before translate
//Alternative would be to simply reverse the original translate
c2d.restore();
};
};
@jsturgis
Copy link
Author

jsturgis commented Mar 9, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment