前几天,单位老刘让我研究一下网上最近很流行的“刮刮卡”是怎么实现的,我第一时间就想起了我媳妇曾经跟我说过的:“在HTML5中Canvas的绘图能力很强大”这句话。所以,我也没多加思考就上网搜集了一些关于HTML5的书籍和资料。为了赶进度,在匆匆阅读之后就开始动手做了起来,再大干了1天之后,终于用“双Canvas技巧”实现了一个蹩脚的刮刮卡功能,难用程度就连自己都觉得非常差劲。


    早上在给老刘看了之后,老刘问了我一些问题,然后就找了一篇资料让我再看一下。研究过后,我发现原来自己由于对HTML5的特性不甚理解,在设计实现的思路上犯了错误。为了完成任务,更为了满足自己的探索欲望,便结合着文章中的示例与自己的一些想法,重新做了一个刮刮卡的实现,这次的实现还算是令我满意,感觉和淘宝在双十一时使用过的刮刮卡差不多了。

下面我就来简单介绍一下我的实现思路:

1、示例中用到的(部分)重要的html5 API介绍

document.querySelector('canvas');
得到页面中canvas元素。
canvas.getContext('2d');
得到绘图的上下文。
ctx.fillStyle = 'transparent';
设置矩形填充的属性,主要为矩形填充方法服务。
ctx.fillRect(0, 0, w, h);
根据给定的坐标与大小绘制一个矩形。
ctx.globalCompositeOperation = 'destination-out';(关键属性)
设置前后绘制的图形组合显示的效果。
ctx.getImageData(0, 10, w, h);
得到图片中的像素数据。
ctx.clearRect(0, 0, w, h);
根据给定的“坐标和大小”,以矩形方式擦掉原图层。
ctx.beginPath();
开始一个新的绘制路径。
ctx.arc(x, y, 25, 0, Math.PI * 2);
根据给定的“坐标,弧度与半径”绘制一条弧线。
ctx.;fill();
绘制后填充。
2、实现思路概述

  1. 在后台根据“用户等级、中奖几率以及其他条件”计算出该用户此次抽奖是否可以抽中,并把计算出来的结果传递给前台页面;
  2. 前台页面再得到了计算结果后,用JS创建一个与计算结果“相符”的“中奖图片”对象;
  3. 设置Canvas的背景为该“中奖图片”;
  4. 在Canvas上绘制一个与“中奖图片”同样大小的“灰色覆盖区域”,以遮挡住图片信息;
  5. 在“灰色覆盖区域”上继续绘制之前,先设置一下图层的叠加方式(设置为:“在已有内容和新图形不重叠的地方,已有内容保留,所有其他内容成为透明。”),用以模拟擦除的效果;
  6. 在“灰色覆盖区域”上,使用算法绘制一条用以模拟手指的擦除效果的弧线;
  7. 当用户“擦除”了一定比例的遮挡区域后,就通知用户是否中奖,同时清除所有的“灰色覆盖区域”,让“中奖图片”完整的显示给用户看,以提升可用性。
3、代码实现

<jsp:directive.page contentType="text/html; charset=UTF-8" language="java" />
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<jsp:directive.page session="false" />
<c:set var="ctxPath" value="${pageContext.request.contextPath}" /><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><meta name="viewport" content="initial-scale=1.0, user-scalable=no" /><style type="text/css">html,body {width: 100%;height: 100%;margin: 0;padding: 0;}body {moz-user-select: none;webkit-user-select: none;}div,select,input,p,ul,li {margin: 0;padding: 0;}body {font-size: 12px;font-family: "宋体";line-height: 2em;}.main {width: 100%;height: 100%;overflow: hidden; hidden;margin: 0;}</style><title>单canvas实现刮刮卡</title></head><body><div id="container" class="main"><canvas/></div></body><script type="text/javascript">(function (bodyStyle) {// 在FF浏览器环境中,通过修改CSS3属性,使子元素中所有的文字都不能选择。bodyStyle.mozUserSelect = 'none';// 在Google浏览器环境中,通过修改CSS3属性,使子元素中所有的文字都不能选择。bodyStyle.webkitUserSelect = 'none';// 得到canvas对象。var canvas = document.querySelector('canvas');var canvasStyle = canvas.style;// 设置canvas的定位方式。canvasStyle.position = 'absolute';// 设置canvas的背景颜色为“透明”。canvasStyle.backgroundColor='transparent';// 构造一个图片对象。var img = new Image();img.src = '${ctxPath}/image/guagua_1canvas.png';// 监听载图片加载事件。img.addEventListener('load', function(e) {var w = img.width,h = img.height;var mousedown = false;// 把canvas的“宽”和“高”设置为图片的宽和高。canvas.width = w;canvas.height = h;// 把canvas移动到屏幕中央。canvas.style.left = ((document.body.clientWidth - w) / 2) + "px";canvas.style.top = ((document.body.clientHeight - h) / 2) + "px";// 把canvas绘布的背景设置为中奖图片。canvas.style.backgroundImage='url('+img.src+')';// 得到绘图的上下文,且绘制一个与中将图片同样大小的透明层。var ctx = canvas.getContext('2d');ctx.fillStyle = 'transparent';ctx.fillRect(0, 0, w, h);// 使用“gray”颜色对canvas画布进行“矩形”填充。ctx.fillStyle = 'gray';ctx.fillRect(0, 0, w, h);// 在已有内容和新图形不重叠的地方,已有内容保留,所有其他内容成为透明。ctx.globalCompositeOperation = 'destination-out';// 处理“鼠标”或“手指”按下时的动作。function eventDown(e){// 通知浏览器不要执行与事件关联的默认动作。e.preventDefault();mousedown = true;}// 处理“鼠标”或“手指”按下后移动时的动作。function eventMove(e){e.preventDefault();if (mousedown) {// 如果存在涉及当前事件的手指的一个列表(这里是指正在移动中的手指)。if (e.changedTouches){// 取得涉及当前事件中众多手指中的最后一个。e = e.changedTouches[e.changedTouches.length - 1];}// 计算当前“鼠标”或“手指”在canvas中的坐标(注意,计算的坐标是canvas里的坐标)。var x = (e.clientX + document.body.scrollLeft || e.pageX) - canvas.offsetLeft || 0,y = (e.clientY + document.body.scrollTop || e.pageY) - canvas.offsetTop || 0;with (ctx) {beginPath();arc(x, y, 25, 0, Math.PI * 2);fill();}}}// 处理“鼠标”或“手指”按下后抬起时的动作。function eventUp(e){e.preventDefault();mousedown = false;// 得到中奖图片的像素数据(像素计算非常耗费CPU和内存,可能会导致浏览器崩溃)。var data = ctx.getImageData(0, 10, w, h).data;// 通过计算每一个像素,得知还有多少“遮挡区域”。for (var i = 0, j = 0; i < data.length; i += 4) {if (data[i] && data[i + 1] && data[i + 2] && data[i + 3]) {j++;}}// 当还只剩下20%的遮挡区域时弹出中奖信息,同时撤掉遮挡区域。if (j <= w * h * 0.35) {alert('恭喜您中了2元现金');ctx.clearRect(0, 0, w, h);}}// 监听“触摸的开始、移动与抬起”事件。canvas.addEventListener('touchstart', eventDown);canvas.addEventListener('touchend', eventUp);canvas.addEventListener('touchmove', eventMove);// 监听“鼠标的开始、移动与抬起”事件。canvas.addEventListener('mousedown', eventDown);canvas.addEventListener('mouseup', eventUp);canvas.addEventListener('mousemove', eventMove);});})(document.body.style);</script></html>

用Canvas实现刮刮卡功能的研究与实践相关推荐

  1. android仿淘宝刮刮卡功能实现

    去年淘宝和天猫的活动搞的有声有色的,其中有一个游戏还是很受大家欢迎的,那就是红包刮刮卡,自己也挺迷的,一刮起来就停不下来,有没有? 最近自己也在学习android入门,正好前些日子在搜索一个功能示例的 ...

  2. 【Unity3D小功能】Unity3D中实现UI擦除效果、刮刮卡功能

    推荐阅读 CSDN主页 GitHub开源地址 Unity3D插件分享 简书地址 我的个人博客 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦. 一.前言 ...

  3. HTML5实现类似刮刮卡的功能

    HTML5实现类似刮刮卡的功能 有这样一个功能,当我们使用微信公众号,发送图片时......此处省略300字! 注意要点设置: 1.设置用户缩放:user-scalable=no|yes <me ...

  4. html5 canvas制作刮刮卡

    下班后,闲着无事,刚好近期在学习画布相关知识,就写了个刮刮卡的demo练一下手,兼容安卓.IOS哦.高手路过,多多指点! 刮刮卡实现原理: 通过canvas绘制一个图片,用户手指触发屏幕时,刮开当前一 ...

  5. 刮刮乐html5效果擦除,利用HTML5的画布Canvas实现刮刮卡效果

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

  6. H5活动刮刮卡功能的实现与注意事项

    7月清仓活动有个刮刮卡的功能.找到了个很好用的插件,但是有个坑搞了我好久.就是当覆盖层是个图片的时候老显示跨域的问题. 先附上页面线上地址. https://m.shandjj.com/index.p ...

  7. 前端遮罩层实现_cocos creator--游戏开奖功能组件《刮刮卡》特效实现

    一. 需求分析 [1]实现手指触摸刮开效果:[2]优化:判断刮开与否(能否正常看到奖项). 二. 游戏场景可视化编辑 三. 手指触摸刮刮卡动态刮开效果的实现 Mask为反向遮罩节点,必须确保大小和位置 ...

  8. html5 刮刮乐 源码,HTML5 canvas实现刮刮乐功能

    最近比较闲,除了在群里给大家交流交流,就没啥学习重心.看了论坛里的各种帖子,各种问题满天飞,这里我就整理了2个h5 canvas的demo,分享给大家! 使用html5的canvas实现刮刮乐功能 舍 ...

  9. canvas绘制刮刮卡,超过一定面积显示全图

    说明:栗子转自简书,在他的基础上添加了重置和超过一定面积显示全图,仅做学习使用.(推荐7.2的代码) 1.前端时间做的一个项目需要支持多终端,网页版需要使用html5中canvas画布对象对一组数据进 ...

最新文章

  1. 京东员工因两年一毛钱没涨而离职,618后跳槽涨薪翻倍
  2. 重磅MIT开源人工智能算法评估和理解对抗Logit配对的稳健性
  3. shell的嵌入命令大全
  4. java float x=26f_东软java笔试题
  5. 【django】配置文件
  6. 个人创业做什么好?以下这几个值得考虑
  7. PAT1004 成绩排名【vector sort排序、string的使用】
  8. mmdnn cannot import caffe
  9. python 代码格式规范脚本_Python编码规范
  10. python允许无止境的循环_ParisGabriel:Python无止境 day03
  11. 带你认识MindSpore量子机器学习库MindQuantum
  12. php判断访问的当前设备是手机还是电脑
  13. 面试题简答题——操作系统相关汇总
  14. python之Excel操作
  15. 华为机试HJ45:名字的漂亮度
  16. linux 创建文件夹快捷方式
  17. 不可能解开的谜题   (程序员修炼之道,评注者序)
  18. R语言金融基础:tidyquant数据整理(滑窗建模)
  19. 计算机三位科学家,华南理工大学这三位年轻科学家太优秀了!
  20. 学习Android studio时的报错Binary XML file line #10: Error inflating class fragment

热门文章

  1. 将个人java web网站发布至公网#内网穿透#花生壳#手把手教程
  2. lib/libSciCamera.so: file not recognized: file format not recognized
  3. java栈和堆的区别_Java中堆和栈的区别
  4. 『Linux基础 - 2 』操作系统,Linux背景知识和Ubuntu操作系统安装
  5. 使用Python实现伪防沉迷工具
  6. Linux基础指令(有图有真相,附实例)
  7. springboot使用POI读取excel数据
  8. VB.net或者C#编写按键精灵DLL教程
  9. 导入HttpPost包
  10. 绝地求生服务器维护9月19日,绝地求生9.19日无法登录游戏解决方法 绝地求生9月19日登录不了?...