今天给大家带来一个刮刮乐的小例子~基于HTML5 canvas的,有兴趣的可以改成Android版本的,或者其他的~ 效果图:
贴一张我中500w的照片,咋办啊,怎么花呢~
好了,下面开始原理: 1、刮奖区域两个Canvas,一个是front , 一个back ,front遮盖住下面的canvas。 2、canvas默认填充了一个矩形,将下面canvas效果图遮盖,然后监听mouse事件,根据mousemove的x,y坐标,进行擦出front canvas上的矩形区域,然后显示出下面的canvas的效果图。 很简单把~嘿嘿~ 1、HTML文件内容:
<!DOCTYPE html>
<html>
<head>
<title></title>
<metacharset="utf-8">
<scripttype="text/javascript"src="../../jquery-1.8.3.js"></script>
<scripttype="text/javascript"src="canvas2d.js"></script>
<scripttype="text/javascript"src="GuaGuaLe2.js"></script>
<scripttype="text/javascript">
$(function ()
{
var guaguale = new GuaGuaLe("front", "back");
guaguale.init({msg: "¥5000000.00"});
});
</script>
<styletype="text/css">
body
{
background: url("s_bd.jpg") repeat 0 0;
}
.container
{
position: relative;
width: 400px;
height: 160px;
margin: 100px auto 0;
background: url(s_title.png) no-repeat 0 0;
background-size: 100% 100%;
}
#front, #back
{
position: absolute;
width: 200px;
left: 50%;
top: 100%;
margin-left: -130px;
height: 80px;
border-radius: 5px;
border: 1px solid #444;
}
</style>
</head>
<body>
<divclass="container">
<canvasid="back"width="200"height="80"></canvas>
<canvasid="front"width="200"height="80"></canvas>
</div>
</body>
</html>
2、首先我利用了一个以前写的canvas辅助类,留下来今天要用的一些方法:
/**
* Created with JetBrains WebStorm.
* User: zhy
* Date: 13-12-17
* Time: 下午9:42
* To change this template use File | Settings | File Templates.
*/
functionCanvas2D($canvas)
{
varcontext = $canvas[0].getContext("2d"),
width = $canvas[0].width,
height = $canvas[0].height,
pageOffset = $canvas.offset();
context.font ="24px Verdana, Geneva, sans-serif";
context.textBaseline ="top";
/**
* 绘制矩形
* @param start
* @param end
* @param isFill
*/
this.drawRect =function(start, end, isFill)
{
varw = end.x - start.x , h = end.y - start.y;
if(isFill)
{
context.fillRect(start.x, start.y, w, h);
}
else
{
context.strokeRect(start.x, start.y, w, h);
}
};
/**
* 根据书写的文本,得到该文本在canvas上书写的中心位置的左上角坐标
* @param text
* @returns {{x: number, y: number}}
*/
this.caculateTextCenterPos =function(text)
{
varmetrics = context.measureText(text);
console.log(metrics);
// context.font = fontSize + "px Verdana, Geneva, sans-serif";
vartextWidth = metrics.width;
vartextHeight = parseInt(context.font);
return{
x: width / 2 - textWidth / 2,
y: height / 2 - textHeight / 2
};
}
this.width =function()
{
returnwidth;
}
this.height =function()
{
returnheight;
}
this.resetOffset =function()
{
pageOffset = $canvas.offset();
}
/**
* 当屏幕大小发生变化,重新计算offset
*/
$(window).resize(function()
{
pageOffset = $canvas.offset();
});
/**
* 将页面上的左边转化为canvas中的坐标
* @param pageX
* @param pageY
* @returns {{x: number, y: number}}
*/
this.getCanvasPoint =function(pageX, pageY)
{
return{
x: pageX - pageOffset.left,
y: pageY - pageOffset.top
}
}
/**
* 清除区域,此用户鼠标擦出刮奖涂层
* @param start
* @returns {*}
*/
this.clearRect =function(start)
{
context.clearRect(start.x, start.y, 10, 10);
returnthis;
};
/**
*将文本绘制到canvas的中间
* @param text
* @param fill
*/
this.drawTextInCenter =function(text, fill)
{
varpoint =this.caculateTextCenterPos(text);
if(fill)
{
context.fillText(text, point.x, point.y);
}
else
{
context.strokeText(text, point.x, point.y);
}
};
/**
* 设置画笔宽度
* @param newWidth
* @returns {*}
*/
this.penWidth =function(newWidth)
{
if(arguments.length)
{
context.lineWidth = newWidth;
returnthis;
}
returncontext.lineWidth;
};
/**
* 设置画笔颜色
* @param newColor
* @returns {*}
*/
this.penColor =function(newColor)
{
if(arguments.length)
{
context.strokeStyle = newColor;
context.fillStyle = newColor;
returnthis;
}
returncontext.strokeStyle;
};
/**
* 设置字体大小
* @param fontSize
* @returns {*}
*/
this.fontSize =function(fontSize)
{
if(arguments.length)
{
context.font = fontSize +"px Verdana, Geneva, sans-serif";
returnthis;
}
returncontext.fontSize;
}
}
这个类也就对Canvas对象进行了简单的封装,设置参数,绘制图形什么的,比较简单,大家可以完善下这个类~ 3、GuaGuaLe.js
/**
* Created with JetBrains WebStorm.
* User: zhy
* Date: 14-6-24
* Time: 上午11:36
* To change this template use File | Settings | File Templates.
*/
functionGuaGuaLe(idFront, idBack)
{
this.$eleBack = $("#"+ idBack);
this.$eleFront = $("#"+ idFront);
this.frontCanvas =newCanvas2D(this.$eleFront);
this.backCanvas =newCanvas2D(this.$eleBack);
this.isStart =false;
}
GuaGuaLe.prototype = {
constructor: GuaGuaLe,
/**
* 将用户的传入的参数和默认参数做合并
* @param desAttr
* @returns {{frontFillColor: string, backFillColor: string, backFontColor: string, backFontSize: number, msg: string}}
*/
mergeAttr:function(desAttr)
{
vardefaultAttr = {
frontFillColor:"silver",
backFillColor:"gold",
backFontColor:"red",
backFontSize: 24,
msg:"谢谢惠顾"
};
for(varpin desAttr)
{
defaultAttr[p] = desAttr[p];
}
returndefaultAttr;
},
init:function(desAttr)
{
varattr =this.mergeAttr(desAttr);
//初始化canvas
this.backCanvas.penColor(attr.backFillColor);
this.backCanvas.fontSize(attr.backFontSize);
this.backCanvas.drawRect({x: 0, y: 0}, {x:this.backCanvas.width(), y:this.backCanvas.height()},true);
this.backCanvas.penColor(attr.backFontColor);
this.backCanvas.drawTextInCenter(attr.msg,true);
//初始化canvas
this.frontCanvas.penColor(attr.frontFillColor);
this.frontCanvas.drawRect({x: 0, y: 0}, {x:this.frontCanvas.width(), y:this.frontCanvas.height()},true);
var_this =this;
//设置事件
this.$eleFront.mousedown(function(event)
{
_this.mouseDown(event);
}).mousemove(function(event)
{
_this.mouseMove(event);
}).mouseup(function(event)
{
_this.mouseUp(event);
});
},
mouseDown:function(event)
{
this.isStart =true;
this.startPoint =this.frontCanvas.getCanvasPoint(event.pageX, event.pageY);
},
mouseMove:function(event)
{
if(!this.isStart)return;
varp =this.frontCanvas.getCanvasPoint(event.pageX, event.pageY);
this.frontCanvas.clearRect(p);
},
mouseUp:function(event)
{
this.isStart =false;
}
};
通过用户传入的两个canvas的id,然后生成一个对象,进行初始化操作,设置事件。当然了也提供用户设置可选的参数,各种颜色,已经刮开后显示的信息等,通过
{
frontFillColor:"silver",
backFillColor:"gold",
backFontColor:"red",
backFontSize: 24,
msg:"谢谢惠顾"
};
传给init方法进行设置。 好了,然后就基本完工了,测试一下: 基本实现了刮开图层,但是存在一个小问题,就是当用户滑动特别快时,会出现一些断点,当然也可以忽略,不过我们准备提供一下解决方案:
产生原因:由于鼠标移动速度过快,产生的断点;解决方案:将mousemove中两次的鼠标左边,进行拆分成多个断点坐标:
如上图,把两点之间进行连线,根据斜率,然后分成多个小段,分别获得线段上的坐标(有四种可能,有兴趣可以画画图,计算下,代码如下):
vark;
if(p.x >this.startPoint.x)
{
k = (p.y -this.startPoint.y) / (p.x -this.startPoint.x);
for(vari =this.startPoint.x; i < p.x; i += 5)
{
this.frontCanvas.clearRect({x: i, y: (this.startPoint.y + (i -this.startPoint.x) * k)});
}
}else
{
k = (p.y -this.startPoint.y) / (p.x -this.startPoint.x);
for(vari =this.startPoint.x; i > p.x; i -= 5)
{
this.frontCanvas.clearRect({x: i, y: (this.startPoint.y + ( i -this.startPoint.x ) * k)});
}
}
this.startPoint = p;
4、最后贴一下完整的GuaGuaLe.js
/**
* Created with JetBrains WebStorm.
* User: zhy
* Date: 14-6-24
* Time: 上午11:36
* To change this template use File | Settings | File Templates.
*/
functionGuaGuaLe(idFront, idBack)
{
this.$eleBack = $("#"+ idBack);
this.$eleFront = $("#"+ idFront);
this.frontCanvas =newCanvas2D(this.$eleFront);
this.backCanvas =newCanvas2D(this.$eleBack);
this.isStart =false;
}
GuaGuaLe.prototype = {
constructor: GuaGuaLe,
/**
* 将用户的传入的参数和默认参数做合并
* @param desAttr
* @returns {{frontFillColor: string, backFillColor: string, backFontColor: string, backFontSize: number, msg: string}}
*/
mergeAttr:function(desAttr)
{
vardefaultAttr = {
frontFillColor:"silver",
backFillColor:"gold",
backFontColor:"red",
backFontSize: 24,
msg:"谢谢惠顾"
};
for(varpin desAttr)
{
defaultAttr[p] = desAttr[p];
}
returndefaultAttr;
},
init:function(desAttr)
{
varattr =this.mergeAttr(desAttr);
//初始化canvas
this.backCanvas.penColor(attr.backFillColor);
this.backCanvas.fontSize(attr.backFontSize);
this.backCanvas.drawRect({x: 0, y: 0}, {x:this.backCanvas.width(), y:this.backCanvas.height()},true);
this.backCanvas.penColor(attr.backFontColor);
this.backCanvas.drawTextInCenter(attr.msg,true);
//初始化canvas
this.frontCanvas.penColor(attr.frontFillColor);
this.frontCanvas.drawRect({x: 0, y: 0}, {x:this.frontCanvas.width(), y:this.frontCanvas.height()},true);
var_this =this;
//设置事件
this.$eleFront.mousedown(function(event)
{
_this.mouseDown(event);
}).mousemove(function(event)
{
_this.mouseMove(event);
}).mouseup(function(event)
{
_this.mouseUp(event);
});
},
mouseDown:function(event)
{
this.isStart =true;
this.startPoint =this.frontCanvas.getCanvasPoint(event.pageX, event.pageY);
},
mouseMove:function(event)
{
if(!this.isStart)return;
varp =this.frontCanvas.getCanvasPoint(event.pageX, event.pageY);
this.frontCanvas.clearRect(p);
},
mouseUp:function(event)
{
this.isStart =false;
}
};
|