canvas 模拟实现电子彩票刮刮乐

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/34089553

今天给大家带来一个刮刮乐的小例子~基于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>
    <meta charset="utf-8">
    <script type="text/javascript" src="../../jquery-1.8.3.js"></script>
    <script type="text/javascript" src="canvas2d.js"></script>
    <script type="text/javascript" src="GuaGuaLe2.js"></script>
    <script type="text/javascript">
        $(function () {
            var guaguale = new GuaGuaLe("front", "back");
            guaguale.init({msg: "¥5000000.00"});
        });
    </script>
    <style type="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>
    <div class="container">
        <canvas id="back" width="200" height="80"></canvas>
        <canvas id="front" width="200" height="80"></canvas>
    </div>
</body>
</html>

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

function Canvas2D($canvas) {
    var context = $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) {
        var w = 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) {
        var metrics = context.measureText(text);
        console.log(metrics);
// context.font = fontSize + "px Verdana, Geneva, sans-serif";
        var textWidth = metrics.width;
        var textHeight = parseInt(context.font);
        return {
            x: width / 2 - textWidth / 2,
            y: height / 2 - textHeight / 2
        };
    }
    this.width = function () {
        return width;
    }
    this.height = function () {
        return height;
    }
    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);
        return this;
    };
    /**
     *将文本绘制到canvas的中间
     * @param text
     * @param fill
     */
    this.drawTextInCenter = function (text, fill) {
        var point = 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;
            return this;
        }
        return context.lineWidth;
    };
    /**
     * 设置画笔颜色
     * @param newColor
     * @returns {*}
     */
    this.penColor = function (newColor) {
        if (arguments.length) {
            context.strokeStyle = newColor;
            context.fillStyle = newColor;
            return this;
        }
        return context.strokeStyle;
    };
    /**
     * 设置字体大小
     * @param fontSize
     * @returns {*}
     */
    this.fontSize = function (fontSize) {
        if (arguments.length) {
            context.font = fontSize + "px Verdana, Geneva, sans-serif";
            return this;
        }
        return context.fontSize;
    }
}

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

3、GuaGuaLe.js

function GuaGuaLe(idFront, idBack) {
    this.$eleBack = $("#" + idBack);
    this.$eleFront = $("#" + idFront);
    this.frontCanvas = new Canvas2D(this.$eleFront);
    this.backCanvas = new Canvas2D(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) {
        var defaultAttr = {
            frontFillColor: "silver",
            backFillColor: "gold",
            backFontColor: "red",
            backFontSize: 24,
            msg: "谢谢惠顾"
        };
        for (var p in desAttr) {
            defaultAttr[p] = desAttr[p];
        }
        return defaultAttr;
    },
    init: function (desAttr) {
        var attr = 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;
        var p = 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中两次的鼠标左边,进行拆分成多个断点坐标:


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

var k;
if (p.x > this.startPoint.x) {
    k = (p.y - this.startPoint.y) / (p.x - this.startPoint.x);
    for (var i = 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 (var i = 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
function GuaGuaLe(idFront, idBack) {
    this.$eleBack = $("#" + idBack);
    this.$eleFront = $("#" + idFront);
    this.frontCanvas = new Canvas2D(this.$eleFront);
    this.backCanvas = new Canvas2D(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) {
        var defaultAttr = {
            frontFillColor: "silver",
            backFillColor: "gold",
            backFontColor: "red",
            backFontSize: 24,
            msg: "谢谢惠顾"
        };
        for (var p in desAttr) {
            defaultAttr[p] = desAttr[p];
        }
        return defaultAttr;
    },
    init: function (desAttr) {
        var attr = 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;
        var p = this.frontCanvas.getCanvasPoint(event.pageX, event.pageY);
        this.frontCanvas.clearRect(p);
    },
    mouseUp: function (event) {
        this.isStart = false;
    }
};

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/34089553

好了,收工吃饭~

源码点击下载

分类HTML5 & CSS3 实战相关推荐:

HTML5 CSS3专题 纯CSS打造相册效果 Html5 Css3实现VCD包装盒个性幻灯片 无插件拖拽上传图片(支持预览与批量)(一) 无插件拖拽上传图片(支持预览与批量)(二) 模仿优酷视频截图功能 CSS3打造百度贴吧的3D翻牌效果 诱人的实例 3D旋转木马效果相册 诱人的实例 3D展示商品信息 canvas 模拟实现电子彩票刮刮乐 3D立方体旋转动画 网页加载进度条的实现,下载进度条等