<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title> - jsFiddle demo by artwl</title>
</head>
<body>
<!--
Author : Yaodongxin
Date : 2016-08-31
Tips : 如果蒙层是图片需要放到服务前环境测试
-->
<button id="freshBtn">刷新</button><label>已刮开 <span id="drawPercent">0%</span> 区域。</label>
<div style="position:relative" id = "card"></div>
<script type='text/javascript'>
var Card = function(options){
this.id = options.id;
this.width = options.width;//如果底层图层是图片,这个值会更新成图片尺寸
this.height = options.height;//如果底层图层是图片,这个值会更新成图片尺寸
this.wrap = null;//包裹canvas的对象
this.mask = null;//蒙层canvas对象
this.bacCtx = null; //context 对象
this.maskCtx = null; //context 对象
this.backType = options.backType || 'text'; // 'image' || 'text'
this.backImg = options.backImg; //刮开后的图层
this.texts = options.texts;//文字串码
this.fontSize = options.fontSize || 36;//文字串码字体大小
this.maskType = options.maskType || 'color';// 'color' || 'image'
this.maskImg = options.maskImg;
this.maskColor = options.maskColor || '#ccc';
this.callback = options.callback || false; //是否执行刮开百分比函数 boollean类型
this.percentDom = options.percentDom || document.getElementById('drawPercent');
}
Card.prototype = {
init : function(){
this.percentDom.innerHTML = '0%';
this.draw();
},
draw : function(){
this.wrap = document.getElementById(this.id);
this.drawMask();
},
// 画底层内容
drawCard : function(){
var _this = this;
_this.resizeCanvas(_this.card, _this.width, _this.height);
_this.bacCtx = _this.card.getContext('2d');
if(_this.backType == 'image'){
if(!_this.backImg){
console.error('A back image url is need.');
}else{
var image = new Image();
image.src = _this.backImg;
image.onload = function(){
_this.width = this.width;
_this.height = this.height;
_this.resizeCanvas(_this.card, this.width, this.height);
_this.bacCtx.drawImage(this, 0, 0); //绘背景图
}
image.error = function(){
console.error('image load failed. Check your url or network.');
}
}
}else{
_this.texts = _this.texts || getRandomStr(6);
_this.bacCtx.font = 'Bold ' + _this.fontSize + 'px "microsoft yahei"';
_this.bacCtx.fillStyle = '#ff6600';
_this.bacCtx.textAlign = 'center';
_this.bacCtx.textBaseline = 'middle';
_this.bacCtx.fillText(_this.texts, _this.width/2, _this.height/2);
}
}, // 绘制蒙层
drawMask : function(){
var _this = this;
// _this.wrap.innerHTML = ''
if(_this.wrap.innerHTML == ''){
_this.mask = document.createElement('canvas');
_this.wrap.appendChild(_this.mask);
_this.mask.setAttribute('style','position:absolute;left:0;top:0;');
_this.card = document.createElement('canvas');
_this.wrap.appendChild(_this.card);
this.bindEvents();
}
_this.resizeCanvas(_this.mask, _this.width, _this.height);
_this.maskCtx = _this.mask.getContext('2d');
if(_this.maskType == 'image'){
if(!_this.maskImg){
console.error('A mask image url is need.');
}else{
var image = new Image();
image.src = _this.maskImg;
image.onload = function(){
_this.maskCtx.drawImage(this, 0, 0); //绘蒙层
_this.drawCard();//绘制随机码
}
image.error = function(){
console.error('image load failed. Check your url or network.');
}
}
}else{
_this.maskCtx.fillStyle = this.maskColor;
_this.maskCtx.fillRect(0, 0, _this.width, _this.height);
_this.drawCard();//绘制随机码
}
_this.clientRect = _this.wrap ? _this.wrap.getBoundingClientRect() : null;
}, // 绘制擦除圆
drawPoint : function(x, y){
this.maskCtx.globalCompositeOperation = 'destination-out';
this.maskCtx.beginPath();
// var radgrad = this.maskCtx.createRadialGradient(x, y, 0, x, y, 30);
// radgrad.addColorStop(0, 'rgba(0, 0, 0, 1)');
// radgrad.addColorStop(1, 'rgba(0, 0, 0, 1)');
radgrad = '#fff';
this.maskCtx.fillStyle = radgrad;
this.maskCtx.arc(x, y, 30, 0, Math.PI * 2, true);
this.maskCtx.fill();
}, //绑定事件
bindEvents : function(){
var _this = this,
device = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase())),
clickEvtName = device ? 'touchstart' : 'mousedown',
moveEvtName = device? 'touchmove': 'mousemove',
isMouseDown = false,
start ={x:0, y:0},
end = {x:0, y:0};
if (!device) {//pc
isMouseDown = false;
document.addEventListener('mouseup', function(e) {
isMouseDown = false;
start ={x:0, y:0};
end = {x:0, y:0};
}, false);
document.addEventListener('mouseout', function(e) {
isMouseDown = false;
start ={x:0, y:0};
end = {x:0, y:0};
}, false);
}else{//mobile
document.addEventListener('touchmove', function(e) {
if (isMouseDown) {
e.preventDefault();
}
}, false);
document.addEventListener('touchend', function(e) {
isMouseDown = false;
start ={x:0, y:0};
end = {x:0, y:0};
}, false);
}
// 绑定擦除事件
var docEle = document.documentElement || document.body;
_this.mask.addEventListener(clickEvtName, function(e){
// console.log(device)
start ={x:0, y:0};
end = {x:0, y:0};
isMouseDown = true;
var x = (device ? e.touches[0].clientX : e.clientX) - _this.clientRect.left + docEle.scrollLeft - docEle.clientLeft;
var y = (device ? e.touches[0].clientY : e.clientY) - _this.clientRect.top + docEle.scrollTop - docEle.clientTop;
_this.drawPoint(x, y);
}, false);
_this.mask.addEventListener(moveEvtName, function(e){
if (!isMouseDown) {
return false;
}
isMouseDown = true;
var x = (device ? e.touches[0].clientX : e.clientX) - _this.clientRect.left + docEle.scrollLeft - docEle.clientLeft;
var y = (device ? e.touches[0].clientY : e.clientY) - _this.clientRect.top + docEle.scrollTop - docEle.clientTop;
if(start.x!=0){
end.x = start.x;
end.y = start.y;
}
start.x = x;
start.y = y;
_this.drawPoint(x, y);
if(end.x!=0){
_this.addDraw(start, end);
}
if(_this.callback){
var percent = _this.drawPercent(_this.maskCtx);
_this.percentDom.innerHTML = percent + '%';
}
}, false);
}, /**
* 这个函数是用来补充move的时候中间的空白
* @param {object} start 形式{x:10,y:10}的对象,画线开始坐标
* @param {object} end 形式{x:20,y:20}的对象,画线结束坐标
*/
addDraw : function(start, end){
var _this = this;
_this.maskCtx.lineWidth = 60;
_this.maskCtx.lineStyle = '#f00';
_this.maskCtx.beginPath();
_this.maskCtx.moveTo(start.x, start.y);
_this.maskCtx.lineTo(end.x, end.y);
_this.maskCtx.stroke();
}, /**
* 重置canvas的宽高
* @param {object} canvas canvas对象
* @param {number} w canvas宽
* @param {number} h canvas高
*/
resizeCanvas : function(canvas, w, h){
canvas.width = w;
canvas.height = h;
}, /**
* 计算刮开的百分比
* @param {object} ctx context2d对象
* @return {number} 刮开图层所占百分比
*/
drawPercent : function(ctx){
var imgData = ctx.getImageData(0, 0, this.width, this.height),
pixles = imgData.data,
transPixs = [],
len = pixles.length;
for(var i = 0; i<len; i+=4){
if(pixles[i+3] == 0){
transPixs.push(pixles[i+3]);
}
}
return (transPixs.length/(len/4)*100).toFixed(2);
}
} /**
* 生成随机串码
* @param {number} len 生成随机串码的长度
* @return {string} 生成的串码
*/
function getRandomStr(len) {
var text = '';
var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for( var i=0; i < len; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
} window.onload = function(){
var card = new Card({
id : 'card',
backType : 'text',
width : '325',
height : '174'
});
card.init(); // 刷新
document.getElementById('freshBtn').addEventListener('click', function(){
card.init();
}, false);
}
</script>
</body>
</html>

demo:预览地址

canvas刮刮卡的更多相关文章

  1. canvas 绘制刮刮卡

    思路=> 用div来展示刮奖结果,用canvas绘制刮奖前展示的图片或者文字:将canvas叠在div上方,刮奖是只需要操作canvas配合touch事件即可简单完成. canvas刮奖可以用g ...

  2. canvas实现刮刮卡效果

    canvas实现刮刮卡效果 实现步骤: 设置页面背景图,即刮刮卡底部图片 绘制canvas 刮刮卡顶部图片drawImage 绑定事件 addEventListener  touchstart.tou ...

  3. qt qml 刮刮卡效果

    用canvas+mouseArea实现的刮刮卡效果. 表层是一层色彩,用手指划开,可看到下面的文字Lisence: MIT, 请保留本文档说明Author: surfsky.cnblogs.com 2 ...

  4. 网页闯关游戏(riddle webgame)--H5刮刮卡的原理和实践

    前言: 之前编写了一个网页闯关游戏(类似Riddle Game), 除了希望大家能够体验一下我的游戏外. 也愿意分享编写这个网页游戏过程中, 学到的一些知识. 对于刮刮卡, 想必大家都很熟悉, 也很喜 ...

  5. Html5实现移动端、PC端 刮刮卡效果

    刚从南方回来就分了一个刮刮卡效果的页面,特么的我在烦恼怎么用H5去实现这个效果呢,好不容易写出来了,产品居然说:“既然你可以写出来这个效果那当然好了,开始我只是打算让你实现点击就出现呢!”… … 尼玛 ...

  6. 用c#开发微信 (16) 微活动 2 刮刮卡

    微信营销是一种新型的营销模式,由于微信更重视用户之间的互动,故而这种营销推广不不能盲目地套用微博营销的单纯大量广告推送方式.这种方式在微信营销中的效果非常差,会令用户反感,继而取消去企业或商家的微信公 ...

  7. Atitit .html5刮刮卡的gui实现总结

    Atitit .html5刮刮卡的gui实现总结 #----两个案例canvas或者wScratchPad-1.4.4 1 #----1.添加panel  ,这个十mask div.....posti ...

  8. 使用HTML5实现刮刮卡效果

    你玩过刮刮卡么?一不小心可以中奖的那种.今天我给大家分享一个基于HTML5技术实现的刮刮卡效果,在PC上只需按住鼠标,在手机上你只需按住指头,轻轻刮去图层就可以模拟真实的刮奖效果. 我们利用HTML5 ...

  9. Android 自定义View修炼-【2014年最后的分享啦】Android实现自定义刮刮卡效果View

    一.简介: 今天是2014年最后一天啦,首先在这里,我祝福大家在新的2015年都一个个的新健康,新收入,新顺利,新如意!!! 上一偏,我介绍了用Xfermode实现自定义圆角和椭圆图片view的博文& ...

  10. Android刮刮卡自定义控件

    网上的都是自己绘制的或者图片,我的需求是可以随意的自定义底部和顶部的布局.所以自己重写一个,原理就是直接继承 View 来实现一个刮层,让这个刮层和图片以及文字不产生任何依赖,再结合 FrameLay ...

随机推荐

  1. &lt;&lt;Python基础教程&gt;&gt;学习笔记 | 第04章 | 字典

    第04章:字典 当索引不好用时 Python唯一的内建的映射类型,无序,但都存储在一个特定的键中.键能够使字符.数字.或者是元祖. ------ 字典使用: 表征游戏棋盘的状态,每一个键都是由坐标值组 ...

  2. eclipse 安装java web插件

    1.eclipse java web搭建以及tomcat配置: http://www.cnblogs.com/yangyxd/articles/5615965.html 注意选择Eclipse IDE ...

  3. 【Android】内存卡图片读取器,图库app

    上一篇<[Android]读取sdcard卡上的全部图片而且显示,读取的过程有进度条显示>(点击打开链接)在真机上測试非常有问题.常常遇到内存溢出.卡死的情况.由于如今真机上的内存上,2G ...

  4. Apache2.4 新virtualhost

    创建配置文件 /etc/apache2/sites-available# sudo nano mysite.conf <VirtualHost *:> #ServerName hello. ...

  5. layui-概念-入门-总结

    layui教程:http://www.dosrun.com/layui/ 获得 Layui你可以在官网首页下载到 Layui 的最新版,也可以通过 GitHub得到Layui的开源包.目前只同步维护这 ...

  6. springboot 项目中控制台打印日志以及每天生成日志文件

    1.控制台打印sql语句 只要在application.properties 中加入<configuration  scan="true" scanPeriod=" ...

  7. 使用OpenGL进行Mandelbrot集的可视化

    Mandelbrot集是哪一集?? Mandelbrot集不是哪一集!! 啊不对-- Mandelbrot集是哪一集!! 好像也不对-- Mandelbrot集是数集!! 所以--他不是一集而是数集? ...

  8. golang中字符串的查找方法小结

    1)func Contains(s, substr string) bool这个函数是查找某个字符是否在这个字符串中存在,存在返回true 示例如下: import ( "fmt" ...

  9. 嵌入式c语言笔试

    1 读程序段,回答问题int main(int argc,char *argv[]){int c=9,d=0;c=c++%5;d=c;printf("d=%d\n",d);retu ...

  10. php eval()计算

    php中的eval()函数可以处理php代码,因此可以用此来解决:以字符串格式存储的计算公式 比如: $str='2*(3+12)'; $s=eval("return $str;" ...