HTML5 Canvas: Lunch Wheel - javascript 룰렛
blog.bramp.net/post/2011/07/27/html5-canvas-lunch-wheel/
HTML5 Canvas: Lunch Wheel
In the on going battle to make my lunch time more optimised I decided to learn some Javascript, and how to use the HTML5 Canvas element. Turns out it’s not that hard, and I have now created Click to …
blog.bramp.net
blog.bramp.net/wheel/
Lunch Wheel
blog.bramp.net
<html > <head >
<meta content ="IE=EmulateIE7" http-equiv ="X-UA-Compatible" >
<title > Lunch Wheel</title >
<link href ="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.css" rel ="stylesheet" type ="text/css" >
<script type ="text/javascript" src ="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" > </script >
<script type ="text/javascript" src ="jquery.tinysort.min.js" > </script >
<script type ="text/javascript" >
shuffle = function (o ) {
for ( var j, x, i = o.length; i; j = parseInt (Math .random() * i), x = o[--i], o[i] = o[j], o[j] = x)
;
return o;
};
String .prototype.hashCode = function ( ) {
var hash = 5381 ;
for (i = 0 ; i < this .length; i++) {
char = this .charCodeAt(i);
hash = ((hash<<5 )+hash) + char;
hash = hash & hash;
}
return hash;
}
Number .prototype.mod = function (n ) {
return ((this %n)+n)%n;
}
</script >
<script type ="text/javascript" >
venues = {
"116208" : "Jerry's Subs and Pizza" ,
"66271" : "Starbucks" ,
"5518" : "Ireland's Four Courts" ,
"392360" : "Five Guys" ,
"2210952" : "Uptown Cafe" ,
"207306" : "Corner Bakery Courthouse" ,
"41457" : "Delhi Dhaba" ,
"101161" : "TNR Cafe" ,
"257424" : "Afghan Kabob House" ,
"512060" : "The Perfect Pita" ,
"66244" : "California Tortilla" ,
"352867" : "Pho 75 - Rosslyn" ,
"22493" : "Ragtime" ,
"268052" : "Subway" ,
"5665" : "Summers Restaurant & Sports Bar" ,
"129724" : "Cosi" ,
"42599" : "Ray's Hell Burger"
};
$(function ( ) {
var venueContainer = $('#venues ul' );
$.each(venues, function (key, item ) {
venueContainer.append(
$(document .createElement("li" ))
.append(
$(document .createElement("input" )).attr({
id : 'venue-' + key
,name : item
,value : item
,type : 'checkbox'
,checked :true
})
.change( function ( ) {
var cbox = $(this )[0 ];
var segments = wheel.segments;
var i = segments.indexOf(cbox.value);
if (cbox.checked && i == -1 ) {
segments.push(cbox.value);
} else if ( !cbox.checked && i != -1 ) {
segments.splice(i, 1 );
}
segments.sort();
wheel.update();
} )
).append(
$(document .createElement('label' )).attr({
'for' : 'venue-' + key
})
.text( item )
)
)
});
$('#venues ul>li' ).tsort("input" , {attr : "value" });
});
</script >
<script type ="text/javascript" >
var wheel = {
timerHandle : 0 ,
timerDelay : 33 ,
angleCurrent : 0 ,
angleDelta : 0 ,
size : 290 ,
canvasContext : null ,
colors : [ '#ffff00' , '#ffc700' , '#ff9100' , '#ff6301' , '#ff0000' , '#c6037e' ,
'#713697' , '#444ea1' , '#2772b2' , '#0297ba' , '#008e5b' , '#8ac819' ],
segments : [],
seg_colors : [],
maxSpeed : Math .PI / 16 ,
upTime : 1000 ,
downTime : 17000 ,
spinStart : 0 ,
frames : 0 ,
centerX : 300 ,
centerY : 300 ,
spin : function ( ) {
if (wheel.timerHandle == 0 ) {
wheel.spinStart = new Date ().getTime();
wheel.maxSpeed = Math .PI / (16 + Math .random());
wheel.frames = 0 ;
wheel.sound.play();
wheel.timerHandle = setInterval (wheel.onTimerTick, wheel.timerDelay);
}
},
onTimerTick : function ( ) {
wheel.frames++;
wheel.draw();
var duration = (new Date ().getTime() - wheel.spinStart);
var progress = 0 ;
var finished = false ;
if (duration < wheel.upTime) {
progress = duration / wheel.upTime;
wheel.angleDelta = wheel.maxSpeed
* Math .sin(progress * Math .PI / 2 );
} else {
progress = duration / wheel.downTime;
wheel.angleDelta = wheel.maxSpeed
* Math .sin(progress * Math .PI / 2 + Math .PI / 2 );
if (progress >= 1 )
finished = true ;
}
wheel.angleCurrent += wheel.angleDelta;
while (wheel.angleCurrent >= Math .PI * 2 )
wheel.angleCurrent -= Math .PI * 2 ;
if (finished) {
clearInterval (wheel.timerHandle);
wheel.timerHandle = 0 ;
wheel.angleDelta = 0 ;
$("#counter" ).html((wheel.frames / duration * 1000 ) + " FPS" );
}
},
init : function (optionList ) {
try {
wheel.initWheel();
wheel.initAudio();
wheel.initCanvas();
wheel.draw();
$.extend(wheel, optionList);
} catch (exceptionData) {
alert('Wheel is not loaded ' + exceptionData);
}
},
initAudio : function ( ) {
var sound = document .createElement('audio' );
sound.setAttribute('src' , 'wheel.mp3' );
wheel.sound = sound;
},
initCanvas : function ( ) {
var canvas = $('#wheel #canvas' ).get(0 );
if ($.browser.msie) {
canvas = document .createElement('canvas' );
$(canvas).attr('width' , 1000 ).attr('height' , 600 ).attr('id' , 'canvas' ).appendTo('.wheel' );
canvas = G_vmlCanvasManager.initElement(canvas);
}
canvas.addEventListener("click" , wheel.spin, false );
wheel.canvasContext = canvas.getContext("2d" );
},
initWheel : function ( ) {
shuffle(wheel.colors);
},
update : function ( ) {
var r = 0 ;
wheel.angleCurrent = ((r + 0.5 ) / wheel.segments.length) * Math .PI * 2 ;
var segments = wheel.segments;
var len = segments.length;
var colors = wheel.colors;
var colorLen = colors.length;
var seg_color = new Array ();
for (var i = 0 ; i < len; i++)
seg_color.push( colors [ segments[i].hashCode().mod(colorLen) ] );
wheel.seg_color = seg_color;
wheel.draw();
},
draw : function ( ) {
wheel.clear();
wheel.drawWheel();
wheel.drawNeedle();
},
clear : function ( ) {
var ctx = wheel.canvasContext;
ctx.clearRect(0 , 0 , 1000 , 800 );
},
drawNeedle : function ( ) {
var ctx = wheel.canvasContext;
var centerX = wheel.centerX;
var centerY = wheel.centerY;
var size = wheel.size;
ctx.lineWidth = 1 ;
ctx.strokeStyle = '#000000' ;
ctx.fileStyle = '#ffffff' ;
ctx.beginPath();
ctx.moveTo(centerX + size - 40 , centerY);
ctx.lineTo(centerX + size + 20 , centerY - 10 );
ctx.lineTo(centerX + size + 20 , centerY + 10 );
ctx.closePath();
ctx.stroke();
ctx.fill();
var i = wheel.segments.length - Math .floor((wheel.angleCurrent / (Math .PI * 2 )) * wheel.segments.length) - 1 ;
ctx.textAlign = "left" ;
ctx.textBaseline = "middle" ;
ctx.fillStyle = '#000000' ;
ctx.font = "2em Arial" ;
ctx.fillText(wheel.segments[i], centerX + size + 25 , centerY);
},
drawSegment : function (key, lastAngle, angle ) {
var ctx = wheel.canvasContext;
var centerX = wheel.centerX;
var centerY = wheel.centerY;
var size = wheel.size;
var segments = wheel.segments;
var len = wheel.segments.length;
var colors = wheel.seg_color;
var value = segments[key];
ctx.save();
ctx.beginPath();
ctx.moveTo(centerX, centerY);
ctx.arc(centerX, centerY, size, lastAngle, angle, false );
ctx.lineTo(centerX, centerY);
ctx.closePath();
ctx.fillStyle = colors[key];
ctx.fill();
ctx.stroke();
ctx.save();
ctx.translate(centerX, centerY);
ctx.rotate((lastAngle + angle) / 2 );
ctx.fillStyle = '#000000' ;
ctx.fillText(value.substr(0 , 20 ), size / 2 + 20 , 0 );
ctx.restore();
ctx.restore();
},
drawWheel : function ( ) {
var ctx = wheel.canvasContext;
var angleCurrent = wheel.angleCurrent;
var lastAngle = angleCurrent;
var segments = wheel.segments;
var len = wheel.segments.length;
var colors = wheel.colors;
var colorsLen = wheel.colors.length;
var centerX = wheel.centerX;
var centerY = wheel.centerY;
var size = wheel.size;
var PI2 = Math .PI * 2 ;
ctx.lineWidth = 1 ;
ctx.strokeStyle = '#000000' ;
ctx.textBaseline = "middle" ;
ctx.textAlign = "center" ;
ctx.font = "1.4em Arial" ;
for (var i = 1 ; i <= len; i++) {
var angle = PI2 * (i / len) + angleCurrent;
wheel.drawSegment(i - 1 , lastAngle, angle);
lastAngle = angle;
}
ctx.beginPath();
ctx.arc(centerX, centerY, 20 , 0 , PI2, false );
ctx.closePath();
ctx.fillStyle = '#ffffff' ;
ctx.strokeStyle = '#000000' ;
ctx.fill();
ctx.stroke();
ctx.beginPath();
ctx.arc(centerX, centerY, size, 0 , PI2, false );
ctx.closePath();
ctx.lineWidth = 10 ;
ctx.strokeStyle = '#000000' ;
ctx.stroke();
},
}
window .onload = function ( ) {
wheel.init();
var segments = new Array ();
$.each($('#venues input:checked' ), function (key, cbox ) {
segments.push( cbox.value );
});
wheel.segments = segments;
wheel.update();
setTimeout (function ( ) {
window .scrollTo(0 , 1 );
}, 0 );
}
</script >
</head >
<body >
<div id ="venues" style ="float:left" > <ul > <li > <input id ="venue-257424" name ="Afghan Kabob House" value ="Afghan Kabob House" type ="checkbox" checked ="checked" > <label for ="venue-257424" > Afghan Kabob House</label > </li > <li > <input id ="venue-66244" name ="California Tortilla" value ="California Tortilla" type ="checkbox" checked ="checked" > <label for ="venue-66244" > California Tortilla</label > </li > <li > <input id ="venue-207306" name ="Corner Bakery Courthouse" value ="Corner Bakery Courthouse" type ="checkbox" checked ="checked" > <label for ="venue-207306" > Corner Bakery Courthouse</label > </li > <li > <input id ="venue-129724" name ="Cosi" value ="Cosi" type ="checkbox" checked ="checked" > <label for ="venue-129724" > Cosi</label > </li > <li > <input id ="venue-41457" name ="Delhi Dhaba" value ="Delhi Dhaba" type ="checkbox" checked ="checked" > <label for ="venue-41457" > Delhi Dhaba</label > </li > <li > <input id ="venue-392360" name ="Five Guys" value ="Five Guys" type ="checkbox" checked ="checked" > <label for ="venue-392360" > Five Guys</label > </li > <li > <input id ="venue-5518" name ="Ireland's Four Courts" value ="Ireland's Four Courts" type ="checkbox" checked ="checked" > <label for ="venue-5518" > Ireland's Four Courts</label > </li > <li > <input id ="venue-116208" name ="Jerry's Subs and Pizza" value ="Jerry's Subs and Pizza" type ="checkbox" checked ="checked" > <label for ="venue-116208" > Jerry's Subs and Pizza</label > </li > <li > <input id ="venue-352867" name ="Pho 75 - Rosslyn" value ="Pho 75 - Rosslyn" type ="checkbox" checked ="checked" > <label for ="venue-352867" > Pho 75 - Rosslyn</label > </li > <li > <input id ="venue-22493" name ="Ragtime" value ="Ragtime" type ="checkbox" checked ="checked" > <label for ="venue-22493" > Ragtime</label > </li > <li > <input id ="venue-42599" name ="Ray's Hell Burger" value ="Ray's Hell Burger" type ="checkbox" checked ="checked" > <label for ="venue-42599" > Ray's Hell Burger</label > </li > <li > <input id ="venue-66271" name ="Starbucks" value ="Starbucks" type ="checkbox" checked ="checked" > <label for ="venue-66271" > Starbucks</label > </li > <li > <input id ="venue-268052" name ="Subway" value ="Subway" type ="checkbox" checked ="checked" > <label for ="venue-268052" > Subway</label > </li > <li > <input id ="venue-5665" name ="Summers Restaurant & Sports Bar" value ="Summers Restaurant & Sports Bar" type ="checkbox" checked ="checked" > <label for ="venue-5665" > Summers Restaurant & Sports Bar</label > </li > <li > <input id ="venue-512060" name ="The Perfect Pita" value ="The Perfect Pita" type ="checkbox" checked ="checked" > <label for ="venue-512060" > The Perfect Pita</label > </li > <li > <input id ="venue-101161" name ="TNR Cafe" value ="TNR Cafe" type ="checkbox" checked ="checked" > <label for ="venue-101161" > TNR Cafe</label > </li > <li > <input id ="venue-2210952" name ="Uptown Cafe" value ="Uptown Cafe" type ="checkbox" checked ="checked" > <label for ="venue-2210952" > Uptown Cafe</label > </li > </ul > </div >
<div id ="wheel" >
<canvas height ="600" id ="canvas" width ="1000" > </canvas >
</div >
<div id ="stats" >
<div id ="counter" > 30.278136368970777 FPS</div >
</div >
</body > </html >