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事件 我就清楚这个计算进程,不占用浏览器的计算线程,这样就不会重复绘制计算像素比例了.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值