canvas画蛋检测


需求:端午节搞一个画蛋的微信游戏,照虚线画好后判定谁最像,画的越好分数越高。

分析:canvas可以实现画蛋,用透明度0的两条线按标准鸡蛋的内径和外径分别画两个椭圆,使用isPointInPath方法可以判断点是否落在某个路径中,因为手绘鸡蛋的线条有粗细,所以要设定落在画板上线条的宽度,在指定宽度内落在内圆与外圆中线中间的就算成功的。每移动一下都记录成功和失败的点,最后计算成功率。为了防止某些怪异画法,又设定了几个边界检查。



demo地址:http://www.free361.com/demo.php?id=1


egg.js

function canvasApp(id,call){
    
    if(!canvasSupport()){
        call(0,"您的浏览器不支持当前页面");
        return;
    }
        
    var canvas_obj = document.getElementById(id);
    var context = canvas_obj.getContext("2d");    //2d上下文对象
    
    context.lineCap = 'square';        //端点样式
    
    var is_mobile = checkMobile();
    var canvas_top = $("#"+id).offset().top;        //画布外框定位
    var canvas_left = $("#"+id).offset().left;
    var count_out = 0;                //圆以外
    var count_in = 0;                //圆以内
    var count_in_out = 0;            //内圆以内
    
    var egg_element;                //蛋蛋定时器
    var egg_cur_pos = [0,0];        //当前笔画坐标
    var egg_org_pos = [138,146];    //中心位置坐标
    var egg_w = 90;                    //蛋宽半径
    var egg_h = 118;                //蛋高半径
    var egg_color = "rgba(211,153,131,0.0)";
    var egg_step_num = 0;            //起始计数
    var egg_flag = 0;                //0绘画未开始,1绘画中,2已完成
    
    //手动画蛋
    var touch_flag = 0;                //手动画的状态0鼠标松开1鼠标按下
    var start_x = 0;                //手动画开始位置
    var start_y = 0;
    var current_x = 0;                //临时变量,当前位置
    var current_y = 0;
    var touch_status = 0;            //0表示未结束1回到起点结束2超出边界失败
    var touch_success_range = 10;    //成功检查范围
    var touch_edge = [0,0,0,0,0,0,0,0];    //手画蛋边界
    
    //计算实际边界
    var egg_edge = [egg_org_pos[0],egg_org_pos[1]-egg_h,egg_org_pos[0]+egg_w,egg_org_pos[1],egg_org_pos[0],egg_org_pos[1]+egg_h,egg_org_pos[0]-egg_w,egg_org_pos[1]];
    
    function canvasSupport(){
        return     Modernizr.canvas;         //检查是否支持canvas
    }
    function checkMobile(){
        return     Modernizr.touchevents;     //检查是否手机浏览器
    }
    
    function drawEgg(){
        context.strokeStyle = egg_color;    //边框颜色
        context.lineWidth = 10;
        
        var x=egg_org_pos[0];
        var y=egg_org_pos[1]-egg_h;
        
        if(egg_cur_pos[0] == 0){
            egg_cur_pos[0] = x;
            egg_cur_pos[1] = y;
        }
        
        context.beginPath();
        
        context.moveTo(egg_cur_pos[0],egg_cur_pos[1]);
        
        var angle = egg_step_num*Math.PI/180;
        
        x = egg_org_pos[0]+egg_w*Math.sin(angle);
        y = egg_org_pos[1]-egg_h*Math.cos(angle);
        
        context.lineTo(x,y);
        
        context.stroke();
        context.closePath();
        
        egg_cur_pos[0] = x;
        egg_cur_pos[1] = y;
        
        egg_step_num++;
        
        if(egg_step_num>=360){
            clearInterval(egg_element);
            
            egg_step_num = 0;
            egg_cur_pos = [0,0];
            egg_flag = 2;
        }
    }
    //自动画蛋
    function startDrawEgg(){
        if(egg_flag == 1){
            return;
        }
        
        //初始化
        egg_flag = 1;
        
        context.clearRect(0,0,270,295); 
        count_out = 0;    
        count_in = 0;    
        count_in_out = 0;    
        touch_status = 0;
        start_x = 0;
        start_y = 0;
        
        egg_element = setInterval(drawEgg,33);
    }
    //蛋底框
    function drawEggOnce(){
        context.strokeStyle = egg_color;    //边框颜色
        context.lineWidth = 10;
        
        var x=egg_org_pos[0];
        var y=egg_org_pos[1]-egg_h;
        
        if(egg_cur_pos[0] == 0){
            egg_cur_pos[0] = x;
            egg_cur_pos[1] = y;
        }
        
        for(var i=0;i<360;i++){
            context.beginPath();
            context.moveTo(egg_cur_pos[0],egg_cur_pos[1]);
            var angle = i*Math.PI/180;
        
            x = egg_org_pos[0]+egg_w*Math.sin(angle);
            y = egg_org_pos[1]-egg_h*Math.cos(angle);
            
            context.lineTo(x,y);
            
            context.stroke();
            
            egg_cur_pos[0] = x;
               egg_cur_pos[1] = y;
               
               context.closePath();
        }

        egg_cur_pos = [0,0];
        egg_flag = 2;
    }
    
    //绑定
    if(is_mobile){
        canvas_obj.addEventListener("touchstart",startDrawSelf,false);
        canvas_obj.addEventListener("touchend",stopDrawSelf,false);
    }else{
        canvas_obj.addEventListener("mousedown",startDrawSelf,false);
        canvas_obj.addEventListener("mouseup",stopDrawSelf,false);
    }
    
    function startDrawSelf(e){
        if(egg_flag<2 || touch_status==1){
            //自动蛋未画完之前不可以手动画
            return;
        }
        
        touch_flag = 1;    //手动画开始
        
        if(is_mobile){
            if (e.targetTouches.length == 1) {
             event.preventDefault();// 阻止浏览器默认事件,重要 
                var touch = e.targetTouches[0];
                
                current_x = touch.pageX-canvas_left;
                current_y = touch.pageY-canvas_top;
                
                canvas_obj.addEventListener("touchmove",drawSelf,false);
            }
            
        }else{
            current_x = e.x-50;
            current_y = e.y-50;
            canvas_obj.addEventListener("mousemove",drawSelf,false);
        }
        
        //记录点击的初始位置
        if(start_x == 0){
            start_x = current_x;
            start_y = current_y;
            
            touch_edge = [current_x,current_y,current_x,current_y,current_x,current_y,current_x,current_y];
        }
        
        call(1,{"x":current_x,"y":current_y});
        
    }
    
    function stopDrawSelf(){
        if(egg_flag<2){
            return;
        }
        touch_flag = 0;        //手动画结束
        
        if(is_mobile){
            canvas_obj.removeEventListener("touchmove",drawSelf,false);
        }else{
            canvas_obj.removeEventListener("mousemove",drawSelf,false);
        }
        
        //判断结果
        var total_in = count_in-count_in_out;
        var total_out = count_out+count_in_out;
        var scale = Math.ceil(total_in*100 / (total_in+total_out));
        //console.log(count_in,count_out,count_in_out,scale);    
        if(touch_status == 1){
            if(scale>90){
                //赢了
//                console.log("赢"+scale+"%");
            }else{
                //输了
//                console.log("输"+scale+"%");
            }
            call(3,{"in":total_in,"out":total_out,"scale":scale});
        }else if(touch_status == 2){
            //犯规
//            console.log("失败");
            call(4,{"in":total_in,"out":total_out,"scale":scale});
        }else{
            //没完成
//            console.log("还没画完"+scale+"%");
            call(5,{"in":total_in,"out":total_out,"scale":scale});
        }
        
    }
    
    function drawSelf(e){
        
        if(egg_flag<2 || touch_flag!=1 || touch_status>0){
            return;
        }
        
        context.strokeStyle = "red";
        context.lineWidth = 8;
        
        if(is_mobile){
            //手机触屏
            if (e.targetTouches.length == 1) {
             event.preventDefault();// 阻止浏览器默认事件,重要 
                var touch = e.targetTouches[0];
                
                //目标坐标
                var mx = touch.pageX-canvas_left;
                var my = touch.pageY-canvas_top;
            }else{
                call(0,"不支持多点触摸");
                return;
            }
            
        }else{
            var mx = e.x-50;
            var my = e.y-50;
        }
        
        context.beginPath();
            
        context.moveTo(current_x,current_y);    
        context.lineTo(mx,my);
        
        context.stroke();
        context.closePath();
        
        current_x = mx;
        current_y = my;
        
        //context,"arc","150,250,120,0,"+2*Math.PI
        var event1=new addEvent(context,"egg","136,146,96,126",mx,my,function(n) {
            //因为beginPath清掉了前面路径的所有绑定,所以这里重新绑定区域的路径
            //大圈
            if(n==1){
                count_in++;
                
//              div_count_box1.innerHTML=count_in-count_in_out;
            }else{
                count_out++;
//              div_count_box2.innerHTML=count_out+count_in_out;
            }
            
            var total_in = count_in-count_in_out;
            var total_out = count_out+count_in_out;
            var scale = Math.ceil(total_in*100 / (total_in+total_out));
            call(2,{"in":total_in,"out":total_out,"scale":scale});
           
        });
        event1.add(mx,my);
        
        var event2=new addEvent(context,"egg","136,146,84,114",mx,my,function(n) {
            //因为beginPath清掉了前面路径的所有绑定,所以这里重新绑定区域的路径
            //小圈
            if(n==1){
                count_in_out++;
                
//              div_count_box1.innerHTML=count_in-count_in_out;
//              div_count_box2.innerHTML=count_out+count_in_out;
            }
            
            var total_in = count_in-count_in_out;
            var total_out = count_out+count_in_out;
            var scale = Math.ceil(total_in*100 / (total_in+total_out));
            call(2,{"in":total_in,"out":total_out,"scale":scale});
            
        });
        event2.add(mx,my);
        
        checkOver();
        
        //记录当前边界
        if(current_y < touch_edge[1] && current_y <touch_edge[3] && current_y < touch_edge[5] && current_y < touch_edge[7]){
            //顶点
            touch_edge[0] = current_x;
            touch_edge[1] = current_y;
        }
        if(current_x > touch_edge[0] && current_x >touch_edge[2] && current_x > touch_edge[4] && current_x > touch_edge[6]){
            //右点
            touch_edge[2] = current_x;
            touch_edge[3] = current_y;
        }
        if(current_y > touch_edge[1] && current_y >touch_edge[3] && current_y > touch_edge[5] && current_y > touch_edge[7]){
            //顶点
            touch_edge[4] = current_x;
            touch_edge[5] = current_y;
        }
        if(current_x < touch_edge[0] && current_x <touch_edge[2] && current_x < touch_edge[4] && current_x < touch_edge[6]){
            //右点
            touch_edge[6] = current_x;
            touch_edge[7] = current_y;
        }

    }
    function checkOver(){
        if(count_in+count_out>50 && touch_status<2){
            
            //检查起始点
            if(start_x <= current_x+touch_success_range && start_x>=current_x-touch_success_range && start_y <= current_y+touch_success_range && start_y>=current_y-touch_success_range){
                //回到原点标记为结束
                touch_status = 1;
                
            }
            
            if(touch_status == 1){
                //边界检查
                var status = 1;
                for(var i =0 ;i<8;i++){
                    if(egg_edge[i]<=touch_edge[i]+50 && egg_edge[i]>=touch_edge[i]-50){
                        
                    }else{
                        //有一个不符合就不通过
                        touch_status = 2;
                    }
                }
            }
        }
    }
    
    function addEvent (cobj,type,data,mx,my,callback) {
        this.cobj=cobj;            //给addEvent增加属性和方法
        this.type=type;
        this.data=data;
        this.callback=callback;
        this.x = mx;
        this.y = my;
        this.redraw();
    }
    
    addEvent.prototype={        //给addEvent原型增加方法
         redraw:function  () {            //重绘
             if(this.type=="arc"){
                 this.cobj.beginPath();
                 this.cobj.strokeStyle = "rgba(255,0,0,0)";
                 this.cobj.lineWidth = 8;
                 var arr=this.data.split(",");
                 this.cobj.arc(arr[0],arr[1],arr[2],arr[3],arr[4]);
                 this.cobj.stroke();
                  
             }else if("egg"){
                 this.cobj.beginPath();
                 this.cobj.strokeStyle = "rgba(0,0,0,0.0)";
                 this.cobj.lineWidth = 8;
                 
                 var arr=this.data.split(",");
        
                 var x = arr[0]*1;
                 var y = arr[1]*1;
                 var a = arr[2]*1;
                 var b = arr[3]*1;
                
                 var step = (a > b) ? 1 / a : 1 / b;
                   
                 this.cobj.moveTo(x + a, y); //从椭圆的左端点开始绘制
                 for (var i = 0; i < 2 * Math.PI; i += step)
                 {
                     //参数方程为x = a * cos(i), y = b * sin(i),
                     //参数为i,表示度数(弧度)
                     this.cobj.lineTo(x + a * Math.cos(i), y + b * Math.sin(i));
                 }
                   
                 this.cobj.stroke();
                
             }
         },
         add:function (mx,my) {
            if(this.cobj.isPointInPath(mx,my)){
                this.callback(1);
            }else{
                this.callback(2);
            }
         }
    }
       

    drawEggOnce();
}

调用:

canvasApp("cas",function(s,msg){
    //status:0 失败,msg:失败原因
    //status 1按下,msg:x,y
    //status:2移动,msg:in,out,scale
    //status:3结束,msg:in,out,scale
    //status:4犯规失败	in,out,scale
    //status:5没完成,松开msg:	in,out,scale
    console.log(s,msg);
		
    if(s == 3){
        current_scale = msg.scale;
        gameOver();
    }else if(s == 4){
        gameOver();
    }
});




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值