canvas刮刮卡
<!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刮刮卡的更多相关文章
- canvas 绘制刮刮卡
思路=> 用div来展示刮奖结果,用canvas绘制刮奖前展示的图片或者文字:将canvas叠在div上方,刮奖是只需要操作canvas配合touch事件即可简单完成. canvas刮奖可以用g ...
- canvas实现刮刮卡效果
canvas实现刮刮卡效果 实现步骤: 设置页面背景图,即刮刮卡底部图片 绘制canvas 刮刮卡顶部图片drawImage 绑定事件 addEventListener touchstart.tou ...
- qt qml 刮刮卡效果
用canvas+mouseArea实现的刮刮卡效果. 表层是一层色彩,用手指划开,可看到下面的文字Lisence: MIT, 请保留本文档说明Author: surfsky.cnblogs.com 2 ...
- 网页闯关游戏(riddle webgame)--H5刮刮卡的原理和实践
前言: 之前编写了一个网页闯关游戏(类似Riddle Game), 除了希望大家能够体验一下我的游戏外. 也愿意分享编写这个网页游戏过程中, 学到的一些知识. 对于刮刮卡, 想必大家都很熟悉, 也很喜 ...
- Html5实现移动端、PC端 刮刮卡效果
刚从南方回来就分了一个刮刮卡效果的页面,特么的我在烦恼怎么用H5去实现这个效果呢,好不容易写出来了,产品居然说:“既然你可以写出来这个效果那当然好了,开始我只是打算让你实现点击就出现呢!”… … 尼玛 ...
- 用c#开发微信 (16) 微活动 2 刮刮卡
微信营销是一种新型的营销模式,由于微信更重视用户之间的互动,故而这种营销推广不不能盲目地套用微博营销的单纯大量广告推送方式.这种方式在微信营销中的效果非常差,会令用户反感,继而取消去企业或商家的微信公 ...
- Atitit .html5刮刮卡的gui实现总结
Atitit .html5刮刮卡的gui实现总结 #----两个案例canvas或者wScratchPad-1.4.4 1 #----1.添加panel ,这个十mask div.....posti ...
- 使用HTML5实现刮刮卡效果
你玩过刮刮卡么?一不小心可以中奖的那种.今天我给大家分享一个基于HTML5技术实现的刮刮卡效果,在PC上只需按住鼠标,在手机上你只需按住指头,轻轻刮去图层就可以模拟真实的刮奖效果. 我们利用HTML5 ...
- Android 自定义View修炼-【2014年最后的分享啦】Android实现自定义刮刮卡效果View
一.简介: 今天是2014年最后一天啦,首先在这里,我祝福大家在新的2015年都一个个的新健康,新收入,新顺利,新如意!!! 上一偏,我介绍了用Xfermode实现自定义圆角和椭圆图片view的博文& ...
- Android刮刮卡自定义控件
网上的都是自己绘制的或者图片,我的需求是可以随意的自定义底部和顶部的布局.所以自己重写一个,原理就是直接继承 View 来实现一个刮层,让这个刮层和图片以及文字不产生任何依赖,再结合 FrameLay ...
随机推荐
- imagemagick imagick
imagemagick#图像处理软件 安装解压 ./configure make make install imagick#是php图像扩展模块 调用imagemagick处理图像 安装解压/opt/ ...
- <<Python基础教程>>学习笔记 | 第04章 | 字典
第04章:字典 当索引不好用时 Python唯一的内建的映射类型,无序,但都存储在一个特定的键中.键能够使字符.数字.或者是元祖. ------ 字典使用: 表征游戏棋盘的状态,每一个键都是由坐标值组 ...
- xshell容易断开的问题
修改服务器的sshd_config文件. http://bbs.51cto.com/thread-904289-1.html
- Nginx多域名多Server反向代理配置
Nginx强大的正则表达式支持,可以使server_name的配置变得很灵活,如果你要做多用户博客,那么每个用户拥有自己的二级域名也就很容易实现了.下面我就来说说server_name的使用吧:ser ...
- eclipse--windowBuilder
https://www.eclipse.org/windowbuilder/ https://www.eclipse.org/windowbuilder/download.php Documentat ...
- python爬虫,从hao123爬取网址信息
最近研究python的爬虫,小小程序,拿下来分享,本人使用python3.7,纯粹兴趣爱好,希望能帮助大家激发兴趣.从hao123,爬取各种网址信息,代码如下. import urllib.reque ...
- nginx could not build the server_names_hash 解决方法
nginx “nginx could not build the server_names_hash”解决方法 给一个服务器下增加了一些站点别名,差不多有20多个. 重启nginx时候,提示: cou ...
- golang生成随机函数的实现
golang生成随机数可以使用math/rand包, 示例如下: package main import ( "fmt" "math/rand" ) func ...
- vue-strap 修改Modal组件
在用到vue-strap的Modal组件时,会有两个默认按钮,查看官方文档配置如下: 可以看到,ok-text和cancel-text都有一个默认值,在使用时即使不给这两个选项赋值,也会显示两个默认文 ...
- 转载 -- 基于原生JS与OC方法互相调用并传值(附HTML代码)
最近项目里面有有个商品活动界面,要与web端传值,将用户在网页点击的商品id 传给客户端,也就是js交互,其实再说明白一点就是方法的互相调用而已. 本文叙述下如何进行原生的JavaScript交互 本 ...