H5 CANVAS 九宫格转盘

使用 H5 的 canvas 绘制的一个九宫格转盘

能够配置每个格子内显示的图片以及文本内容

点击 开始 旋转光圈,停止后显示选中格的内容

DEMO运行效果:点击查看

HTML代码

<div class="sudoku">
<canvas class="face"></canvas>
<canvas class="rotation"></canvas>
<div class="controlBtn"></div>
<img src="img/gift.png" id="gift" />
<img src="img/smile.png" id="smile" />
</div>

CSS代码

.sudoku {
position: absolute;
top: 20px;
left: 50%;
width: 512px;
height: 433px;
margin-left: -256px;
}
.sudoku canvas {
position: absolute;
top: 0;
left: 0;
}
.sudoku .controlBtn {
position: absolute;
cursor: pointer;
-webkit-tap-highlight-color : rgba(0,0,0,0);
-moz-tap-highlight-color : rgba(0,0,0,0);
-ms-tap-highlight-color : rgba(0,0,0,0);
-o-tap-highlight-color : rgba(0,0,0,0);
tap-highlight-color : rgba(0,0,0,0);
-webkit-tap-highlight-color :transparent;
-moz-tap-highlight-color :transparent;
-ms-tap-highlight-color :transparent;
-o-tap-highlight-color :transparent;
tap-highlight-color :transparent;
}
.sudoku img {
display: none;
}

JS代码

<script type="text/javascript" src="js/zepto.min.js"></script>
<script type="text/javascript" src="js/sudoku.js"></script>
<script type="text/javascript">
var items = [
{text:"100M"},
{text:"谢谢参与"},
{text:"300M"},
{text:"谢谢参与"},
{text:""},
{text:"谢谢参与"},
{text:"500M"},
{text:"谢谢参与"},
{text:"200M"}
],sudoku;
window.onload = function(){
sudoku = $(".sudoku").sudoku({
items : items
}).data("sudoku");
sudoku = $.fn.sudoku.lookup[sudoku];
};
$(window).on("resize",function(){
sudoku.init();
});
</script>

九宫格转盘JS插件源码

(function($){
var Sudoku, privateMethod;
Sudoku = (function(){
function Sudoku(element, options){
var $this = this;
$this.el = element;
$this.options = $.extend({}, $.fn.sudoku.defaults, options);
$this.init();
}
Sudoku.prototype = {
init : function(){
var $this = this;
var cxt = $this.initElement();
$this.render(cxt.face);
$this.ready(cxt.rotation);
},
initElement : function(){
var $this = this;
$this.width = $this.el.width();
$this.height = $this.el.height();
$this.boxWidth = $this.width*290/1024;
$this.boxHeight = $this.height*243/865;
$this.boxBorderTop = $this.height*7/865;
$this.boxBorderLeft = $this.width*9/1024;
var ml = $this.width*61/1024,
mt = $this.height*50/865,
bm = $this.width/64, i,j;
$this.boxs = [];
for(i=0;i<3;++i){
for(j=0;j<3;++j){
$this.boxs.push({x: ml+j*($this.boxWidth+bm), y: mt+i*($this.boxHeight+bm)});
}
}
$this.controlBtn = $this.el.children(".controlBtn").css({top: $this.boxs[4].y, left: $this.boxs[4].x, width: $this.boxWidth, height: $this.boxHeight});
return {
face : $this.el.children(".face").attr({width: $this.width, height: $this.height})[0].getContext("2d"),
rotation : $this.el.children(".rotation").attr({width: $this.width, height: $this.height})[0].getContext("2d")
};
},
render : function(cxt){
cxt.clearRect(0,0,this.width,this.height);
var $this = this,
x, y, sw,
i, j, len;
sw = $this.width*3/512;
x = $this.width*39/1024 + sw;
y = $this.height*33/865 + sw;
cxt.save();
cxt.beginPath();
privateMethod.rect(cxt,sw,sw,$this.width-2*sw,$this.height-2*sw,false);
privateMethod.rect(cxt,x,y,$this.width-2*x,$this.height-2*y,true);
cxt.fillStyle = "#691c14";
cxt.shadowBlur = $this.width*3/256;
cxt.shadowColor = "#691c14";
cxt.fill();
cxt.restore();
cxt.save();
cxt.beginPath();
privateMethod.rect(cxt,x,y,$this.width-2*x,$this.height-2*y,true);
cxt.fillStyle = "#340808";
cxt.fill();
cxt.restore();
x = $this.width*21/1024 + sw;
y = $this.height*18/865 + sw;
sw = $this.width*7/1024;
var lights = [
{x: x, y: y, ax: ($this.width-2*x)/12, ay: 0, num: 12},
{x: $this.width-x, y: y, ax: 0, ay:($this.height-2*y)/11, num: 11},
{x: $this.width-x, y: $this.height-y, ax: -($this.width-2*x)/12, ay: 0, num: 12},
{x: x, y: $this.height-y, ax: 0, ay: -($this.height-2*y)/11, num: 11}
];
cxt.shadowBlur = sw;
cxt.shadowColor = "#fecb02";
cxt.fillStyle = "#fecb02";
for(i=0;i<lights.length;++i){
x = lights[i].x;
y = lights[i].y;
for(j=0;j<lights[i].num;++j){
cxt.save();
cxt.translate(x,y);
cxt.beginPath();
cxt.arc(0,0,sw,0,Math.PI*2);
cxt.closePath();
cxt.fill();
cxt.restore();
x += lights[i].ax;
y += lights[i].ay;
}
}
var linear1 = cxt.createLinearGradient(0,0,0,$this.boxHeight),
linear2 = cxt.createLinearGradient(0,0,0,$this.boxHeight),
linear3 = cxt.createLinearGradient(0,0,$this.boxWidth,$this.boxHeight);
linear1.addColorStop(0,"#ffe484");
linear1.addColorStop(1,"#ffeba1");
linear2.addColorStop(0,"#fdd135");
linear2.addColorStop(1,"#ffbf12");
linear3.addColorStop(0,"#e92121");
linear3.addColorStop(.076,"#e92121");
linear3.addColorStop(.076,"#f03e3e");
linear3.addColorStop(.152,"#f03e3e");
linear3.addColorStop(.152,"#e92121");
linear3.addColorStop(.228,"#e92121");
linear3.addColorStop(.228,"#f03e3e");
linear3.addColorStop(.304,"#f03e3e");
linear3.addColorStop(.304,"#e92121");
linear3.addColorStop(.38,"#e92121");
linear3.addColorStop(.38,"#f03e3e");
linear3.addColorStop(.456,"#f03e3e");
linear3.addColorStop(.456,"#e92121");
linear3.addColorStop(.532,"#e92121");
linear3.addColorStop(.532,"#f03e3e");
linear3.addColorStop(.608,"#f03e3e");
linear3.addColorStop(.608,"#e92121");
linear3.addColorStop(.684,"#e92121");
linear3.addColorStop(.684,"#f03e3e");
linear3.addColorStop(.76,"#f03e3e");
linear3.addColorStop(.76,"#e92121");
linear3.addColorStop(.836,"#e92121");
linear3.addColorStop(.836,"#f03e3e");
linear3.addColorStop(.912,"#f03e3e");
linear3.addColorStop(.912,"#e92121");
linear3.addColorStop(1,"#e92121");
len = $this.options.items.length;
cxt.shadowBlur = 0;
cxt.font = $this.boxWidth*36/290+"px Helvetica";
cxt.textBaseline = "top";
cxt.textAlign = "center";
x = $this.boxWidth/2;
y = $this.boxHeight*165/243;
var w = $this.boxWidth*104/290,
h = $this.boxHeight*128/243,
x1 = ($this.boxWidth-w)/ 2,
y1 = $this.boxHeight*30/243,
imgs = {
gift : document.getElementById("gift"),
smile : document.getElementById("smile")
};
for(i=0;i<len;++i){
cxt.save();
cxt.translate($this.boxs[i].x,$this.boxs[i].y);
cxt.beginPath();
privateMethod.rect(cxt,0,0,$this.boxWidth,$this.boxHeight,true);
cxt.closePath();
i&1 && (cxt.fillStyle = linear1) || i !== Math.floor(len/2) && (cxt.fillStyle = linear2);
cxt.fill();
cxt.fillStyle = "#691c14";
cxt.fillText($this.options.items[i].text,x,y);
if(i&1){
imgs.smile.onload = function(){
cxt.drawImage(this,x1,y1,w,w);
};
cxt.drawImage(imgs.smile,x1,y1,w,w);
}
else{
imgs.gift.onload = function(){
cxt.drawImage(this,x1,y1,w,h);
};
cxt.drawImage(imgs.gift,x1,y1,w,h);
}
cxt.restore();
}
cxt.save();
cxt.translate($this.boxs[4].x,$this.boxs[4].y);
cxt.beginPath();
privateMethod.rect(cxt,0,0,$this.boxWidth,$this.boxHeight,true);
cxt.closePath();
cxt.fillStyle = linear3;
cxt.fill();
cxt.fillStyle = "#fd5354";
privateMethod.rectBorder(cxt,0,0,$this.boxBorderTop,$this.boxBorderLeft,$this.boxWidth,$this.boxHeight);
cxt.fill();
cxt.fillStyle ="#fdf402";
cxt.font = $this.boxWidth*8/29+"px Microsoft YaHei";
cxt.textBaseline = "bottom";
cxt.textAlign = "center";
cxt.fillText("开始",$this.boxWidth/2,$this.boxHeight/2);
cxt.textBaseline = "top";
cxt.fillText("抽奖",$this.boxWidth/2,$this.boxHeight/2);
cxt.restore();
},
ready : function(cxt){
cxt.clearRect(0,0,this.width,this.height);
cxt.fillStyle = "#e92121";
privateMethod.rectBorder(cxt,this.boxs[0].x,this.boxs[0].y,this.boxBorderTop,this.boxBorderLeft,this.boxWidth,this.boxHeight);
cxt.fill();
this.next = 1;
this.dir = [0,1,2,5,8,7,6,3];
this.isRotating = false;
var $this = this;
this.controlBtn.on("click tap",function(){
if($this.isRotating) return;
$this.isRotating = true;
var num = Math.floor(Math.random()*$this.options.items.length);
num = privateMethod.indexOf($this.dir,num);
num === -1 && (num = 0);
$this.rotate(cxt, 200, $this.next, num);
});
},
rotate : function(cxt, speed, index, num){
cxt.clearRect(0,0,this.width,this.height);
var len = this.dir.length,
$this = this;
privateMethod.rectBorder(cxt,this.boxs[this.dir[index%len]].x,this.boxs[this.dir[index%len]].y,this.boxBorderTop,this.boxBorderLeft,this.boxWidth,this.boxHeight);
cxt.fill();
if(index >= (privateMethod.baseRounds+2)*len && index%len === num){
clearTimeout(this.timer);
setTimeout(function(){
alert("text: "+$this.options.items[$this.dir[num]].text);
$this.next = (num+1)%len;
$this.isRotating = false;
},1000);
}
else{
if(index < privateMethod.baseRounds*len){
speed -= 20;
}
else{
speed += 30;
}
speed = speed<80 ? 80 : speed;
this.timer = setTimeout(function(){
$this.rotate(cxt,speed,++index,num)
},speed);
}
}
};
return Sudoku;
})();
privateMethod = {
baseRounds : 3,
drawImage : function(img,callback){
if( img.complete ){
callback.call(img);
return;
}
img.onload = function(){
callback.call(img);
}
},
rect : function(cxt, x, y, width, height, c){
cxt.moveTo(x,y);
if(c){
cxt.lineTo(x, y+height);
cxt.lineTo(x+width, y+height);
cxt.lineTo(x+width, y);
cxt.lineTo(x, y);
}
else {
cxt.lineTo(x+width, y);
cxt.lineTo(x+width, y+height);
cxt.lineTo(x, y+height);
cxt.lineTo(x, y);
}
},
rectBorder : function(cxt, x, y, borderTop, borderLeft, width, height){
cxt.beginPath();
privateMethod.rect(cxt,x,y,width,height,true);
privateMethod.rect(cxt,x+borderLeft,y+borderTop,width-2*borderLeft,height-2*borderTop,false);
cxt.closePath();
},
arc : function(cxt, x, y, radius, c){
cxt.beginPath();
cxt.arc(x,y,radius,0,Math.PI*2,c);
cxt.closePath();
},
indexOf : function(arr, val){
var l = arr.length,i;
for(i=0;i<l;++i) if(arr[i]===val) return i;
return -1;
}
};
$.fn.sudoku = function(options){
return this.each(function(){
var $this = $(this),
instance = $.fn.sudoku.lookup[$this.data("sudoku")];
if(!instance){
instance = new Sudoku($this, options);
$.fn.sudoku.lookup[++$.fn.sudoku.lookup.i] = instance;
$this.data("sudoku", $.fn.sudoku.lookup.i)
}
if(typeof options === "string"){
instance[options]();
}
});
};
$.fn.sudoku.lookup = {
i : 0
};
$.fn.sudoku.defaults = {
};
})(Zepto);
Show comments from Gitment