指引网

当前位置: 主页 > 网页制作 > HTML >

HTML5+CSS3实例 :canvas 模拟实现电子彩票刮刮乐

来源:网络 作者:佚名 点击: 时间:2017-07-06 20:59
[摘要]  这篇文章介绍了HTML5+CSS3中canvas模拟实现电子彩票刮刮乐的例子,有兴趣的同学可以参考一下

今天给大家带来一个刮刮乐的小例子~基于HTML5 canvas的,有兴趣的可以改成Android版本的,或者其他的~

效果图:

贴一张我中500w的照片,咋办啊,怎么花呢~

好了,下面开始原理:

1、刮奖区域两个Canvas,一个是front , 一个back ,front遮盖住下面的canvas。

2、canvas默认填充了一个矩形,将下面canvas效果图遮盖,然后监听mouse事件,根据mousemove的x,y坐标,进行擦出front canvas上的矩形区域,然后显示出下面的canvas的效果图。

很简单把~嘿嘿~

1、HTML文件内容:

<!DOCTYPE html> 
<html> 
<head> 
    <title></title> 
    <metacharset="utf-8"> 
   
    <scripttype="text/javascript"src="../../jquery-1.8.3.js"></script> 
    <scripttype="text/javascript"src="canvas2d.js"></script> 
   
    <scripttype="text/javascript"src="GuaGuaLe2.js"></script> 
   
    <scripttype="text/javascript"> 
   
        $(function () 
        { 
            var guaguale = new GuaGuaLe("front", "back"); 
            guaguale.init({msg: "¥5000000.00"}); 
        }); 
    </script> 
    <styletype="text/css"> 
   
   
        body 
        { 
            background: url("s_bd.jpg") repeat 0 0; 
        } 
   
        .container 
        { 
            position: relative; 
            width: 400px; 
            height: 160px; 
            margin: 100px auto 0; 
            background: url(s_title.png) no-repeat 0 0; 
            background-size: 100% 100%; 
        } 
   
        #front, #back 
        { 
            position: absolute; 
            width: 200px; 
            left: 50%; 
            top: 100%; 
            margin-left: -130px; 
            height: 80px; 
            border-radius: 5px; 
            border: 1px solid #444; 
        } 
   
    </style> 
   
</head> 
<body> 
   
<divclass="container"> 
    <canvasid="back"width="200"height="80"></canvas> 
    <canvasid="front"width="200"height="80"></canvas> 
</div> 
   
   
</body> 
</html> 

2、首先我利用了一个以前写的canvas辅助类,留下来今天要用的一些方法:

/**
 * Created with JetBrains WebStorm.
 * User: zhy
 * Date: 13-12-17
 * Time: 下午9:42
 * To change this template use File | Settings | File Templates.
 */ 
   
functionCanvas2D($canvas) 
    varcontext = $canvas[0].getContext("2d"), 
        width = $canvas[0].width, 
        height = $canvas[0].height, 
        pageOffset = $canvas.offset(); 
   
   
    context.font ="24px Verdana, Geneva, sans-serif"; 
    context.textBaseline ="top"; 
   
   
    /**
     * 绘制矩形
     * @param start
     * @param end
     * @param isFill
     */ 
    this.drawRect =function(start, end, isFill) 
    { 
        varw = end.x - start.x , h = end.y - start.y; 
        if(isFill) 
        { 
            context.fillRect(start.x, start.y, w, h); 
        } 
        else 
        { 
            context.strokeRect(start.x, start.y, w, h); 
        } 
    }; 
   
    /**
     * 根据书写的文本,得到该文本在canvas上书写的中心位置的左上角坐标
     * @param text
     * @returns {{x: number, y: number}}
     */ 
    this.caculateTextCenterPos =function(text) 
    { 
        varmetrics = context.measureText(text); 
        console.log(metrics); 
//        context.font = fontSize + "px Verdana, Geneva, sans-serif"; 
        vartextWidth = metrics.width; 
        vartextHeight = parseInt(context.font); 
   
        return{ 
            x: width / 2 - textWidth / 2, 
            y: height / 2 - textHeight / 2 
        }; 
    } 
    this.width =function() 
    { 
        returnwidth; 
    } 
    this.height =function() 
    { 
        returnheight; 
    } 
    this.resetOffset =function() 
    { 
        pageOffset = $canvas.offset(); 
    } 
    /**
     * 当屏幕大小发生变化,重新计算offset
     */ 
    $(window).resize(function() 
    { 
        pageOffset = $canvas.offset(); 
    }); 
   
    /**
     * 将页面上的左边转化为canvas中的坐标
     * @param pageX
     * @param pageY
     * @returns {{x: number, y: number}}
     */ 
    this.getCanvasPoint =function(pageX, pageY) 
    { 
        return{ 
            x: pageX - pageOffset.left, 
            y: pageY - pageOffset.top 
        } 
    } 
    /**
     * 清除区域,此用户鼠标擦出刮奖涂层
     * @param start
     * @returns {*}
     */ 
    this.clearRect =function(start) 
    { 
        context.clearRect(start.x, start.y, 10, 10); 
        returnthis; 
    }; 
   
    /**
     *将文本绘制到canvas的中间
     * @param text
     * @param fill
     */ 
    this.drawTextInCenter =function(text, fill) 
    { 
        varpoint =this.caculateTextCenterPos(text); 
        if(fill) 
        { 
            context.fillText(text, point.x, point.y); 
        } 
        else 
        { 
            context.strokeText(text, point.x, point.y); 
        } 
    }; 
    /**
     * 设置画笔宽度
     * @param newWidth
     * @returns {*}
     */ 
    this.penWidth =function(newWidth) 
    { 
        if(arguments.length) 
        { 
            context.lineWidth = newWidth; 
            returnthis; 
        } 
        returncontext.lineWidth; 
    }; 
   
    /**
     * 设置画笔颜色
     * @param newColor
     * @returns {*}
     */ 
    this.penColor =function(newColor) 
    { 
        if(arguments.length) 
        { 
            context.strokeStyle = newColor; 
            context.fillStyle = newColor; 
            returnthis; 
        } 
   
        returncontext.strokeStyle; 
    }; 
   
    /**
     * 设置字体大小
     * @param fontSize
     * @returns {*}
     */ 
    this.fontSize =function(fontSize) 
    { 
        if(arguments.length) 
        { 
            context.font = fontSize +"px Verdana, Geneva, sans-serif"; 
   
            returnthis; 
        } 
   
        returncontext.fontSize; 
    } 
   
   

这个类也就对Canvas对象进行了简单的封装,设置参数,绘制图形什么的,比较简单,大家可以完善下这个类~

3、GuaGuaLe.js

/**
 * Created with JetBrains WebStorm.
 * User: zhy
 * Date: 14-6-24
 * Time: 上午11:36
 * To change this template use File | Settings | File Templates.
 */ 
functionGuaGuaLe(idFront, idBack) 
    this.$eleBack = $("#"+ idBack); 
    this.$eleFront = $("#"+ idFront); 
    this.frontCanvas =newCanvas2D(this.$eleFront); 
    this.backCanvas =newCanvas2D(this.$eleBack); 
   
    this.isStart =false; 
   
   
GuaGuaLe.prototype = { 
    constructor: GuaGuaLe, 
    /**
     * 将用户的传入的参数和默认参数做合并
     * @param desAttr
     * @returns {{frontFillColor: string, backFillColor: string, backFontColor: string, backFontSize: number, msg: string}}
     */ 
    mergeAttr:function(desAttr) 
    { 
        vardefaultAttr = { 
            frontFillColor:"silver", 
            backFillColor:"gold", 
            backFontColor:"red", 
            backFontSize: 24, 
            msg:"谢谢惠顾" 
        }; 
        for(varpin desAttr) 
        { 
            defaultAttr[p] = desAttr[p]; 
        } 
   
        returndefaultAttr; 
   
    }, 
   
   
    init:function(desAttr) 
    { 
   
        varattr =this.mergeAttr(desAttr); 
   
        //初始化canvas 
        this.backCanvas.penColor(attr.backFillColor); 
        this.backCanvas.fontSize(attr.backFontSize); 
        this.backCanvas.drawRect({x: 0, y: 0}, {x:this.backCanvas.width(), y:this.backCanvas.height()},true); 
        this.backCanvas.penColor(attr.backFontColor); 
        this.backCanvas.drawTextInCenter(attr.msg,true); 
        //初始化canvas 
        this.frontCanvas.penColor(attr.frontFillColor); 
        this.frontCanvas.drawRect({x: 0, y: 0}, {x:this.frontCanvas.width(), y:this.frontCanvas.height()},true); 
   
        var_this =this; 
        //设置事件 
        this.$eleFront.mousedown(function(event) 
        { 
            _this.mouseDown(event); 
        }).mousemove(function(event) 
            { 
                _this.mouseMove(event); 
            }).mouseup(function(event) 
            { 
                _this.mouseUp(event); 
            }); 
    }, 
    mouseDown:function(event) 
    { 
        this.isStart =true; 
        this.startPoint =this.frontCanvas.getCanvasPoint(event.pageX, event.pageY); 
    }, 
    mouseMove:function(event) 
    { 
        if(!this.isStart)return; 
        varp =this.frontCanvas.getCanvasPoint(event.pageX, event.pageY); 
        this.frontCanvas.clearRect(p); 
    }, 
    mouseUp:function(event) 
    { 
        this.isStart =false; 
    } 
}; 

通过用户传入的两个canvas的id,然后生成一个对象,进行初始化操作,设置事件。当然了也提供用户设置可选的参数,各种颜色,已经刮开后显示的信息等,通过

{
            frontFillColor:"silver",
            backFillColor:"gold",
            backFontColor:"red",
            backFontSize: 24,
            msg:"谢谢惠顾"
        };

传给init方法进行设置。

好了,然后就基本完工了,测试一下:

基本实现了刮开图层,但是存在一个小问题,就是当用户滑动特别快时,会出现一些断点,当然也可以忽略,不过我们准备提供一下解决方案:

产生原因:由于鼠标移动速度过快,产生的断点;解决方案:将mousemove中两次的鼠标左边,进行拆分成多个断点坐标:

如上图,把两点之间进行连线,根据斜率,然后分成多个小段,分别获得线段上的坐标(有四种可能,有兴趣可以画画图,计算下,代码如下):

vark; 
      if(p.x >this.startPoint.x) 
      { 
          k = (p.y -this.startPoint.y) / (p.x -this.startPoint.x); 
          for(vari =this.startPoint.x; i < p.x; i += 5) 
          { 
              this.frontCanvas.clearRect({x: i, y: (this.startPoint.y + (i -this.startPoint.x) * k)}); 
          } 
      }else 
      { 
          k = (p.y -this.startPoint.y) / (p.x -this.startPoint.x); 
          for(vari =this.startPoint.x; i > p.x; i -= 5) 
          { 
              this.frontCanvas.clearRect({x: i, y: (this.startPoint.y + ( i -this.startPoint.x  ) * k)}); 
          } 
      } 
      this.startPoint = p;

4、最后贴一下完整的GuaGuaLe.js


/**
 * Created with JetBrains WebStorm.
 * User: zhy
 * Date: 14-6-24
 * Time: 上午11:36
 * To change this template use File | Settings | File Templates.
 */ 
functionGuaGuaLe(idFront, idBack) 
    this.$eleBack = $("#"+ idBack); 
    this.$eleFront = $("#"+ idFront); 
    this.frontCanvas =newCanvas2D(this.$eleFront); 
    this.backCanvas =newCanvas2D(this.$eleBack); 
   
    this.isStart =false; 
   
   
GuaGuaLe.prototype = { 
    constructor: GuaGuaLe, 
    /**
     * 将用户的传入的参数和默认参数做合并
     * @param desAttr
     * @returns {{frontFillColor: string, backFillColor: string, backFontColor: string, backFontSize: number, msg: string}}
     */ 
    mergeAttr:function(desAttr) 
    { 
        vardefaultAttr = { 
            frontFillColor:"silver", 
            backFillColor:"gold", 
            backFontColor:"red", 
            backFontSize: 24, 
            msg:"谢谢惠顾" 
        }; 
        for(varpin desAttr) 
        { 
            defaultAttr[p] = desAttr[p]; 
        } 
   
        returndefaultAttr; 
   
    }, 
   
   
    init:function(desAttr) 
    { 
   
        varattr =this.mergeAttr(desAttr); 
   
        //初始化canvas 
        this.backCanvas.penColor(attr.backFillColor); 
        this.backCanvas.fontSize(attr.backFontSize); 
        this.backCanvas.drawRect({x: 0, y: 0}, {x:this.backCanvas.width(), y:this.backCanvas.height()},true); 
        this.backCanvas.penColor(attr.backFontColor); 
        this.backCanvas.drawTextInCenter(attr.msg,true); 
        //初始化canvas 
        this.frontCanvas.penColor(attr.frontFillColor); 
        this.frontCanvas.drawRect({x: 0, y: 0}, {x:this.frontCanvas.width(), y:this.frontCanvas.height()},true); 
   
        var_this =this; 
        //设置事件 
        this.$eleFront.mousedown(function(event) 
        { 
            _this.mouseDown(event); 
        }).mousemove(function(event) 
            { 
                _this.mouseMove(event); 
            }).mouseup(function(event) 
            { 
                _this.mouseUp(event); 
            }); 
    }, 
    mouseDown:function(event) 
    { 
        this.isStart =true; 
        this.startPoint =this.frontCanvas.getCanvasPoint(event.pageX, event.pageY); 
    }, 
    mouseMove:function(event) 
    { 
        if(!this.isStart)return; 
        varp =this.frontCanvas.getCanvasPoint(event.pageX, event.pageY); 
        this.frontCanvas.clearRect(p); 
    }, 
    mouseUp:function(event) 
    { 
        this.isStart =false; 
    } 
}; 


------分隔线----------------------------