本文主要是介绍Canvas 刮刮乐,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
demo1手机端 demo2手机+PC<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=640,user-scalable=no,target-densitydpi=device-dpi" /><meta name="apple-mobile-web-app-capable" content="yes"/><meta name="apple-mobile-web-app-status-bar-style" content="black"/><meta name="format-detection" content="telephone=no"/><style>*{margin:0;padding:0;}body{max-width:640px;width:100%;margin:0 auto;height:100%;position:absolute;}.txt{width:100%;height:100%;max-width:640px;}.txt img{width:100%;max-width:640px;height:100%;}.can{position: absolute;top:0;left:0;width:100%;}#Mycanvas{opacity: 1;-webkit-transition: opacity .5s;-ms-transition: opacity .5s;-moz-transition: opacity .5s;}.Mycanvas{opacity:0!important;}</style></head><body><section class="bg"><div class="txt"><img src="images/2.jpg" alt="" /></div><div class="can"><canvas id="Mycanvas"></canvas></div></section></body><script>!(function(doc){var MyCanvas=doc.querySelector("#Mycanvas"),cont=MyCanvas.getContext("2d"),dataArr=[],a=false,stop=startx=starty=movex=movey=timer=null,disyance=30,hastouch = "ontouchstart" in window?true:false,tapstart=hastouch?"touchstart":"mousedown",tapmove=hastouch?"touchmove":"mousemove",tapend=hastouch?"touchend":"mouseup";MyCanvas.width=window.innerWidth;MyCanvas.height=853;/*** *兼容动画函数* @param {Function} callback [description]* @return {[type]} [description]*/// window.requestAnimFrame = (function(callback) {// return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||// function(callback) {// window.setTimeout(callback, 1000 / 60);// };// })(); // var cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame;/*** *引入图片 转化成Canvas* @return {[type]} [description]*/function cvsToImg(){var img=new Image();img.src="images/1.jpg";// img.crossOrigin = "Anonymous";img.οnlοad=function(){cont.drawImage(img,0,0);//文章的核心 设置源和目标的重叠区域为透明cont.globalCompositeOperation="destination-out";} }cvsToImg(); /*** *触摸事件绑定*/MyCanvas.addEventListener(tapstart,start,false);/*** *开始挂* @param {[type]} event [description]* @return {[type]} [description]*/function start(event){/**清楚像素值计算计时器**/clearTimeout(timer);var touch=hastouch?event.targetTouches[0]:null;//获取初始坐标startx=hastouch?touch.pageX-getPos(MyCanvas).x1:event.clientX-getPos(MyCanvas).x1;starty=hastouch?touch.pageY-getPos(MyCanvas).y1:event.clientY-getPos(MyCanvas).y1;/**事件绑定**/MyCanvas.addEventListener(tapmove,move,false);MyCanvas.addEventListener(tapend,end,false);event.preventDefault();} function move(event){//清楚计算透明度计时器clearTimeout(timer);var touch=hastouch?event.targetTouches[0]:null;//移动的坐标movex=hastouch?touch.pageX-getPos(MyCanvas).x1:event.clientX-getPos(MyCanvas).x1;movey=hastouch?touch.pageY-getPos(MyCanvas).y1:event.clientY-getPos(MyCanvas).y1;cont.beginPath();cont.strokeStyle="rgba(255,255,255,1)";cont.lineWidth=60;cont.lineCap="round"; //设置线条两端为圆弧cont.lineJoin="round";cont.moveTo(startx,starty);cont.lineTo(movex,movey);cont.stroke();cont.closePath();//设置线条转折为圆弧startx=movex;starty=movey;event.preventDefault();}function end(event){timer=setTimeout(function(){var imgData=cont.getImageData(0,0,window.innerWidth,853);dataSize=imgData.data.length,count=0;for (var x =0; x<imgData.width; x+=disyance) {for (var y = 0; y < imgData.height; y+=disyance) {var i=(y*imgData.width+x)*4;if(imgData.data[i+3]==0)count++;};};if(count/(imgData.width*imgData.height/(disyance*disyance))>0.6&&!a){MyCanvas.className="Mycanvas";a=true;}},100)MyCanvas.removeEventListener(tapmove,move,false);event.preventDefault();}/*** *获取离文档的编剧* @param {[type]} elm [description]* @return {[type]} [description]*/function getPos(elm){var tops=elm.getBoundingClientRect().top+(document.body.scrollTop||document.documentElement.scrollTop), //获取上边距和左边距lefts=elm.getBoundingClientRect().left+(document.body.scrollLeft||document.documentElement.scrollLeft);return {"x1":lefts,"y1":tops};}/*** *随机生成中奖下标* @param {[type]} num [description]* @return {[type]} [description]*/// function randomInRange(num){// var ranDom=Math.floor(Math.random()*num);// console.log(ranDom);// return txtArr[ranDom];// }/*** 计算颜色个数* @param {[type]} child [description]* @param {[type]} parentArr [description]* @return {[type]} [description]*/// function perCent(child,parentArr){// var count=0;// for (var i = 0; i < parentArr.length; i++) {// if(parentArr[i]==child)count++;// };// return count;// }// function drwas(gloBal){// cont.globalAlpha=gloBal/100;// console.log(cont.globalAlpha);// } // function upData(){// gloBa-=globalSpeed;// if(gloBa<0){// gloBa=0;// cancelAnimationFrame(stop);// console.log(gloBa);// console.log(stop);// }else{// stop=requestAnimationFrame(upData);// }// // drwas(gloBa); // MyCanvas.style.opacity=gloBa/100; // }})(document)</script>
</html>
定义两个结构 一个底图,一个Canvas
本文章的核心是讲 cont.globalCompositeOperation="destination-out"; 这个属性,目标与源的重叠是透明的 这样我们就思路出来了,把要掩盖的图片引入进Canvas里面,就是要擦掉的图片,在手机或者电脑上手指移动 的时候我们再画布目标上不断画一个源出来,这样不就是目标和源重叠了吗,重叠的地方透明了,被掩盖的底图就出来了。
hastouch = "ontouchstart" in window?true:false,
tapstart=hastouch?"touchstart":"mousedown",
tapmove=hastouch?"touchmove":"mousemove",
tapend=hastouch?"touchend":"mouseup";
首先我看实在移动端还是在PC端
ontouchstart in window 来判断,后面三个start move end 就可以决定是用touch 还是mouse ;
cont.drawImage(img,0,0);
引入要被擦得图片进去Canvas
接着start事件包含move和end连个事件 开始进行绘制 end事件触发的时候记得解绑move以免重复绑定。
if(count/(imgData.width*imgData.height/(disyance*disyance))>0.6&&!a){MyCanvas.className="Mycanvas";a=true;}
关于这个0.6是什么,就是当你绘制的图形大于整个画布部分的60%; 然后canvas就自动消失,显示底部,一般我们刮刮乐的时候,不会全部挂完就显示出来,就是这个效果。
timer=setTimeout(function(){var imgData=cont.getImageData(0,0,window.innerWidth,853);dataSize=imgData.data.length,count=0;for (var x =0; x<imgData.width; x+=disyance) {for (var y = 0; y < imgData.height; y+=disyance) {var i=(y*imgData.width+x)*4;if(imgData.data[i+3]==0)count++;};};if(count/(imgData.width*imgData.height/(disyance*disyance))>0.6&&!a){MyCanvas.className="Mycanvas";a=true;}},100
手指一离开的时候,利用getImageData()方法返回的data属性来获取整个画布的像素值rgba 四个点的值,但是一个画布很大,我们不可能每个点都去采集获取,那样性能就很低了,会很卡,利用采样的方法进行
disyance=30
这个30代表了我没30*30像素我取一个像素点来获取rgba中的a值,既然cont.globalCompositeOperation="destination-out"; 那透明每个像素点的a值都是0 取每30*30像素的第一个像素中的a,(小图的话 采样的宽和高可以小一点),如果的等于a==0 我的计数器count++;count必须定义在end方法里面。每次都要清空不能定义全局对象.
count/(imgData.width*imgData.height/(disyance*disyance))>0.6
技术除以采样范围就可以得到百分比了,这样我们不要全部擦完就可以得到底图。
最后说一下
setTimeout
我再end里面定义了一个定时器,意思就是离开之后不马上计算,隔一会儿,但是更重要的原因就是性能,离开之后又触发start事件 我就清楚这个计算进程,不占用浏览器的计算线程,这样就不会重复绘制计算像素比例了.
这篇关于Canvas 刮刮乐的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!