移动端刮刮乐的实现方式(js+HTML5)


Posted in Javascript onMarch 23, 2017

程序员有一种惯性思维,就是看见一些会动的东西(带点科技含量的,猫啊,狗啊就算了),总要先想一遍,这玩意用代码是怎么控制的。比如电梯,路边的霓虹灯,遥控器,小孩子的玩具等,都统统被程序员“意淫”过。

有时候还会感觉程序员看世界会看的透彻一点.............

想必大家都玩过刮刮乐,下面就介绍一种刮刮乐的移动端实现方式!用到canvas

1、用HTML 5 canvas globalCompositeOperation 属性实现刮刮乐

思路:

(1)首先需要一个盒子定位,确定刮刮乐区域想要放在哪里

(2)定位盒子里有个放内容的盒子,也就是放奖品的

(3)用一个画布(canvas)把上面的盒子盖住

(4)当手触摸移动的时候,可以擦除部分画布,露出奖品区

(5)当擦除足够多(3/4)的时候,可以选择让画布自动消失,慢慢淡出(这个效果选做)

主要是第四步,如何擦除?

这里选用 globalCompositeOperation,即Canvas中的合成操作。简单来说,Composite(组合),就是对你在绘图中,后绘制的图形与先绘制的图形之间的组合显示效果,比如在国画中,你先画一笔红色,再来一笔绿色,相交的部分是一种混色,而在油画中,绿色就会覆盖掉相交部分的红色,这在程序绘图中的处理就是Composite,Canvas API中对应的函数就是globalCompositeOperation。

globalCompositeOperation中有个属性值是“destination-out",也就是当绘画重叠时显示透明。刚好用到这里,我们就可以在画布上乱画,画过的地方就是重叠的地方,就会变成透明,然后露出画布下的东西,也就是我们想要的效果。

html 代码如下:

<!DOCTYPE html>
<html>
 <head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
 <title></title>
 <link rel="stylesheet" type="text/css" href="css/guaguale.css" rel="external nofollow" />
 </head>
 <body>
 <!-- 大的背景盒子-->
 <div id="main">
  <!-- 定位的盒子-->
  <div class="canvasBox">
  <!-- 放内容的盒子-->
  <span id="prize">
   恭喜发财,红包拿来
  </span>
  <!-- 蒙版画布-->
  <canvas id="canvas"></canvas>
  </div>
 </div>
 </body>
 <script type="text/javascript">
 var canvas = document.getElementById("canvas");
 var ctx = canvas.getContext('2d');
 /* 画布偏移量,下面用到的时候再介绍*/
 var arr = getOffset(canvas);
 var oLeft = arr[0];
 var oTop = arr[1];
 /* 初始化画布*/
 ctx.beginPath();
 ctx.fillStyle = '#ccc';
 ctx.fillRect(0,0,canvas.width,canvas.height);
 ctx.closePath();
 /* 增加触摸监听*/
 document.addEventListener("touchstart",function(){
  /* 初始化画笔*/
  ctx.beginPath();
  /* 画笔粗细*/
  ctx.lineWidth = 30;
  /* 设置组合效果*/
  ctx.globalCompositeOperation = 'destination-out';
  /* 移动画笔原点*/
  ctx.moveTo(event.touches[0].pageX-oLeft,event.touches[0].pageY-oTop);
 },false)
 document.addEventListener("touchmove",function(){
  /* 根据手指移动画线,使之变透明*/
  ctx.lineTo(event.touches[0].pageX-oLeft,event.touches[0].pageY-oTop);
  /* 填充*/
  ctx.stroke();
 })
 /* 之所以会用到下面的那个函数getOffset(obj)
  * 是因为event.touches[0].pageX、pageY获取的是相对于可视窗口的距离
  * 而lineTo画笔的定位是根据画布位置定位的
  * 所以就要先获取到画布(canvas)相对于可视窗口的距离,然后计算得出触摸点相对于画布的距离 
  * */
 /* 获取该元素到可视窗口的距离*/
 function getOffset(obj){
  var valLeft = 0,valTop = 0;
  function get(obj){
  valLeft += obj.offsetLeft;
  valTop += obj.offsetTop;
  /* 不到最外层就一直调用,直到offsetParent为body*/
  if (obj.offsetParent.tagName!='BODY') {
   get(obj.offsetParent);
  }
  return [valLeft,valTop];
  }
  return get(obj);
 }
 </script>
</html>

css代码如下:

*{
 margin: 0;
 padding: 0;
}
#main{
 width: 100%;
 padding: 20px 0;
 background-color: red;
}

.canvasBox{
 width: 78%;
 height: 160px;
 border-radius: 10px;
 background-color: #FFF;
 margin-left: 11%;
 line-height: 160px;
 text-align: center;
 position: relative;
}
#canvas{
 width: 96%;
 height: 96%;
 position: absolute;
 left: 2%;
 top: 2%;
 background-color: transparent;
}

第五步要用到canvas像素点的获取(这块注意,像素级操作,要在服务器环境下打开)

getImageData(int x,int y,int width,int height):该方法获取canvas上从(x,y)点开始,宽为width、高为height的图片区域的数据,该方法返回的是一个CanvasPixelArray对象,该对象具有width、height、data等属性。data属性为一个数组,该数组每4个元素对应一个像素点。

(对图片的反相操作也可以这样做,改变rgba值)

getImageData(int x,int y,int width,int height)返回的对象,data里面存储的是像素点信息

移动端刮刮乐的实现方式(js+HTML5)

我们再打印data,data属性为一个数组,每4个元素对应一个像素点(以rgba的形式保存每一个像素点的信息)。

移动端刮刮乐的实现方式(js+HTML5)

所以我们就可以根据像素点的opcity值来判断这个像素点是不是透明,是不是等于0?

透明的像素点数量/总像素点数量 = 擦除比例

js代码:

document.addEventListener("touchend",function(){
  /* 获取imageData对象*/
  var imageDate = ctx.getImageData(0,0,canvas.width,canvas.height);
  /* */
  var allPX = imageDate.width * imageDate.height;
  
  var iNum = 0;//记录刮开的像素点个数
  
  for(var i=0;i<allPX;i++){
  if(imageDate.data[i*4+3] == 0){
   iNum++;
  }
  }
  if(iNum >= allPX*3/4){
  // disappear里面写了缓慢清除的css3动画效果
  canvas.setAttribute('class','disappear'); 
  }
 },false)

" .disappear " 的css样式,css3消失动画

.disappear{
 -webkit-animation: disa 2s 1;
 animation: disa 2s 1;
 -webkit-animation-fill-mode: forwards;
 -moz-animation-fill-mode: forwards;
 -o-animation-fill-mode: forwards;
 animation-fill-mode: forwards;
}
@keyframes disa{
 0%{opacity:1;}
 100%{opacity: 0;}
}

相对比网上的其他一些实现方式,这种还是比较简单的一种,大家相互学习。有什么其他的办法可以留言相互学习

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
javascript 多种搜索引擎集成的页面实现代码
Jan 02 Javascript
jquery ajax jsonp跨域调用实例代码
Dec 11 Javascript
简单的jQuery入门指引
Jul 28 Javascript
通过javascript进行UTF-8编码的实现方法
Jun 27 Javascript
jQuery Ajax自定义分页组件(jquery.loehpagerv1.0)实例详解
May 01 jQuery
Vue2 使用 Echarts 创建图表实例代码
May 18 Javascript
hammer.js实现图片手势放大效果
Aug 29 Javascript
使用命令行工具npm新创建一个vue项目的方法
Dec 27 Javascript
jQuery封装animate.css的实例
Jan 04 jQuery
jQuery AJAX与jQuery事件的分析讲解
Feb 18 jQuery
Vue中axios的封装(报错、鉴权、跳转、拦截、提示)
Aug 20 Javascript
js 实现watch监听数据变化的代码
Oct 13 Javascript
BootStrap+Mybatis框架下实现表单提交数据重复验证
Mar 23 #Javascript
jquery实现全选、全不选以及单选功能
Mar 23 #jQuery
jQuery插件FusionCharts实现的MSBar3D图效果示例【附demo源码】
Mar 23 #jQuery
纯jQuery实现前端分页功能
Mar 23 #jQuery
vue双向绑定简要分析
Mar 23 #Javascript
Javascript面试经典套路reduce函数查重
Mar 23 #Javascript
JQuery 进入页面默认给已赋值的复选框打钩
Mar 23 #jQuery
You might like
Php图像处理类代码分享
2012/01/19 PHP
php版微信公众平台回复中文出现乱码问题的解决方法
2016/09/22 PHP
JQuery 学习技巧总结
2010/05/21 Javascript
Js与下拉列表处理问题解决
2014/02/13 Javascript
如何设置一定时间内只能发送一次请求
2014/02/28 Javascript
javascript正则匹配汉字、数字、字母、下划线
2014/04/10 Javascript
javascript中setTimeout和setInterval的unref()和ref()用法示例
2014/11/26 Javascript
sails框架的学习指南
2014/12/22 Javascript
Nodejs学习笔记之Global Objects全局对象
2015/01/13 NodeJs
JS控制表格实现一条光线流动分割行的方法
2015/03/09 Javascript
使用javascript提交form表单方法汇总
2015/06/25 Javascript
JavaScript实现的浮动层框架用法实例分析
2015/10/10 Javascript
每天一篇javascript学习小结(RegExp对象)
2015/11/17 Javascript
基于jquery实现弹幕效果
2016/09/29 Javascript
vue实现ToDoList简单实例
2017/02/07 Javascript
基于Datatables跳转到指定页的简单实例
2017/11/09 Javascript
Javascript实现购物车功能的详细代码
2018/05/08 Javascript
原生JS封装_new函数实现new关键字的功能
2018/08/12 Javascript
webpack 最佳配置指北(推荐)
2020/01/07 Javascript
vue-路由精讲 二级路由和三级路由的作用
2020/08/06 Javascript
Python的IDEL增加清屏功能实例
2017/06/19 Python
pandas数据清洗,排序,索引设置,数据选取方法
2018/05/18 Python
Python+selenium实现自动循环扔QQ邮箱漂流瓶
2018/05/29 Python
Python+Pandas 获取数据库并加入DataFrame的实例
2018/07/25 Python
Python实现的连接mssql数据库操作示例
2018/08/17 Python
python安装pil库方法及代码
2019/06/25 Python
Python的Lambda函数用法详解
2019/09/03 Python
详解Python3迁移接口变化采坑记
2019/10/11 Python
RentCars.com巴西:汽车租赁网站
2016/08/22 全球购物
在线实验室测试:HealthLabs.com
2020/05/03 全球购物
培训心得体会
2013/12/29 职场文书
感情真挚的毕业生求职信
2014/07/19 职场文书
关于读书的演讲稿800字
2014/08/27 职场文书
小学语文复习计划
2015/01/19 职场文书
MySQL和Oracle批量插入SQL的通用写法示例
2021/11/17 MySQL
解决linux下redis数据库overcommit_memory问题
2022/02/24 Redis