<!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. cocos2d-x 3.0游戏实例学习笔记 《跑酷》移植到android手机

    说明:这里是借鉴:晓风残月前辈的博客.他是将泰然网的跑酷教程.用cocos2d-x 2.X 版本号重写的,眼下我正在学习cocos2d-X3.0 于是就用cocos2d-X 3.0重写,并做相关笔记 ...

  2. 微信小程序(应用号)开发新闻客户端的实战课程

    摘要: 本实例将演示从零开发一个微信应用号的过程,页面轮播与跳转传值,实现单元格自定义布局,全部源码可通过github下载. 下载最新版的微信小程序开发工具,目前是v0.9.092300 下载地址:h ...

  3. el表达式注意

    如果action那边是String类型,el表达式进行判断的时候必须加引号,即使是数字也要加. 否则可能导致windows正常,linux出错.

  4. apache common包 CollectionUtils 使用 详解

    集合判断:  例1: 判断集合是否为空: CollectionUtils.isEmpty(null): true CollectionUtils.isEmpty(new ArrayList()): t ...

  5. URL Handle in Swift (二) — 响应链处理 URL

    最后更新: Swift4时候的博客,以前在 CMD markdown 上编辑的,现在搬到这里 在上篇文章-URL Handle in Swift (一) -- URL 分解中,我们已经将URL进行了分 ...

  6. GenericServlet 、Servlet和httpServler他们之间的关系

    1.GenericServlet类是所有Servlet类的祖先类. 2.HttpServlet类继承了GenericServlet类. 3.Servlet有两个非常重要的的对象,可以说是java we ...

  7. CentOS6下基于Nginx搭建mp4/flv流媒体服务器

    CentOS6下基于Nginx搭建mp4/flv流媒体服务器(可随意拖动)并支持RTMP/HLS协议(含转码工具) 1.先添加几个RPM下载源 1.1)安装RPMforge的CentOS6源 [roo ...

  8. Android TextView setText卡顿问题

    TextView 是经常使用控件之中的一个,最经常使用的方法是setText()  . 可是 我们在显示大量的文本的时候,使用setText还是会有一些性能的问题. 这篇文章 关于TextView的s ...

  9. urllib库python2和python3具体区别

      Python 2 name Python 3 name urllib.urlretrieve() urllib.request.urlretrieve() urllib.urlcleanup() ...

  10. Java 集成域登陆

    参考: 1. JAVA中使用jcifs集成AD域用户认证 2. https://liaosy.iteye.com/blog/1887092 3.其他库 https://github.com/Waffl ...