canvas实现刮奖功能

news2024/11/27 21:06:56

canvas刮奖原理很简单,就是在刮奖区添加两个canvas,第一个canvas用于显示刮开后显示的内容,可以是一张图片或一个字符串,第二个canvas用于显示涂层,可以用一张图片或用纯色填充,第二个canvas覆盖在第一个canvas上面。

当在第二个canvas上点击或涂抹(点击然后拖动鼠标)时,把点击区域变为透明,这样就可以看到第一个canvas上的内容,即实现了刮奖效果。

效果图

在这里插入图片描述

源代码


							<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>_直接复制网</title>
<meta name="viewport" content="width=device-width, initial-scale=1 ,user-scalable=no">
<script src="http://libs.baidu.com/jquery/2.1.1/jquery.min.js"></script>
<style>
#lotteryContainer {
    position:relative;
    width: 300px;
    height:100px;
}
#drawPercent {
    color:#F60;
}
</style>
</head>
<body>
<button id="freshBtn">刷新</button><label>已刮开 <span id="drawPercent">0%</span> 区域。</label>
<div id="lotteryContainer"></div>

<script>
function Lottery(id, cover, coverType, width, height, drawPercentCallback) {
    this.conId = id;
    this.conNode = document.getElementById(this.conId);
    this.cover = cover;
    this.coverType = coverType;
    this.background = null;
    this.backCtx = null;
    this.mask = null;
    this.maskCtx = null;
    this.lottery = null;
    this.lotteryType = 'image';
    this.width = width || 300;
    this.height = height || 100;
    this.clientRect = null;
    this.drawPercentCallback = drawPercentCallback;
}

Lottery.prototype = {
    createElement: function (tagName, attributes) {
        var ele = document.createElement(tagName);
        for (var key in attributes) {
            ele.setAttribute(key, attributes[key]);
        }
        return ele;
    },
    getTransparentPercent: function(ctx, width, height) {
        var imgData = ctx.getImageData(0, 0, width, height),
            pixles = imgData.data,
            transPixs = [];
        for (var i = 0, j = pixles.length; i < j; i += 4) {
            var a = pixles[i + 3];
            if (a < 128) {
                transPixs.push(i);
            }
        }
        return (transPixs.length / (pixles.length / 4) * 100).toFixed(2);
    },
    resizeCanvas: function (canvas, width, height) {
        canvas.width = width;
        canvas.height = height;
        canvas.getContext('2d').clearRect(0, 0, width, height);
    },
    drawPoint: function (x, y) {
        this.maskCtx.beginPath();
        var radgrad = this.maskCtx.createRadialGradient(x, y, 0, x, y, 30);
        radgrad.addColorStop(0, 'rgba(0,0,0,0.6)');
        radgrad.addColorStop(1, 'rgba(255, 255, 255, 0)');
        this.maskCtx.fillStyle = radgrad;
        this.maskCtx.arc(x, y, 30, 0, Math.PI * 2, true);
        this.maskCtx.fill();
        if (this.drawPercentCallback) {
            this.drawPercentCallback.call(null, this.getTransparentPercent(this.maskCtx, this.width, this.height));
        }
    },
    bindEvent: function () {
        var _this = this;
        var device = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
        var clickEvtName = device ? 'touchstart' : 'mousedown';
        var moveEvtName = device? 'touchmove': 'mousemove';
        if (!device) {
            var isMouseDown = false;
            document.addEventListener('mouseup', function(e) {
                isMouseDown = false;
            }, false);
        } else {
            document.addEventListener("touchmove", function(e) {
                if (isMouseDown) {
                    e.preventDefault();
                }
            }, false);
            document.addEventListener('touchend', function(e) {
                isMouseDown = false;
            }, false);
        }
        this.mask.addEventListener(clickEvtName, function (e) {
            isMouseDown = true;
            var docEle = document.documentElement;
            if (!_this.clientRect) {
                _this.clientRect = {
                    left: 0,
                    top:0
                };
            }
            var x = (device ? e.touches[0].clientX : e.clientX) - _this.clientRect.left + docEle.scrollLeft - docEle.clientLeft;
            var y = (device ? e.touches[0].clientY : e.clientY) - _this.clientRect.top + docEle.scrollTop - docEle.clientTop;
            _this.drawPoint(x, y);
        }, false);

        this.mask.addEventListener(moveEvtName, function (e) {
            if (!device && !isMouseDown) {
                return false;
            }
            var docEle = document.documentElement;
            if (!_this.clientRect) {
                _this.clientRect = {
                    left: 0,
                    top:0
                };
            }
            var x = (device ? e.touches[0].clientX : e.clientX) - _this.clientRect.left + docEle.scrollLeft - docEle.clientLeft;
            var y = (device ? e.touches[0].clientY : e.clientY) - _this.clientRect.top + docEle.scrollTop - docEle.clientTop;
            _this.drawPoint(x, y);
        }, false);
    },
    drawLottery: function () {
        this.background = this.background || this.createElement('canvas', {
            style: 'position:absolute;left:0;top:0;'
        });
        this.mask = this.mask || this.createElement('canvas', {
            style: 'position:absolute;left:0;top:0;'
        });

        if (!this.conNode.innerHTML.replace(/[\w\W]| /g, '')) {
            this.conNode.appendChild(this.background);
            this.conNode.appendChild(this.mask);
            this.clientRect = this.conNode ? this.conNode.getBoundingClientRect() : null;
            this.bindEvent();
        }

        this.backCtx = this.backCtx || this.background.getContext('2d');
        this.maskCtx = this.maskCtx || this.mask.getContext('2d');

        if (this.lotteryType == 'image') {
            var image = new Image(),
                _this = this;
            image.onload = function () {
                _this.width = this.width;
                _this.height = this.height;
                _this.resizeCanvas(_this.background, this.width, this.height);
                _this.backCtx.drawImage(this, 0, 0);
                _this.drawMask();
            }
            image.src = this.lottery;
        } else if (this.lotteryType == 'text') {
            this.width = this.width;
            this.height = this.height;
            this.resizeCanvas(this.background, this.width, this.height);
            this.backCtx.save();
            this.backCtx.fillStyle = '#FFF';
            this.backCtx.fillRect(0, 0, this.width, this.height);
            this.backCtx.restore();
            this.backCtx.save();
            var fontSize = 30;
            this.backCtx.font = 'Bold ' + fontSize + 'px Arial';
            this.backCtx.textAlign = 'center';
            this.backCtx.fillStyle = '#F60';
            this.backCtx.fillText(this.lottery, this.width / 2, this.height / 2 + fontSize / 2);
            this.backCtx.restore();
            this.drawMask();
        }
    },
    drawMask: function() {
        this.resizeCanvas(this.mask, this.width, this.height);
        if (this.coverType == 'color') {
            this.maskCtx.fillStyle = this.cover;
            this.maskCtx.fillRect(0, 0, this.width, this.height);
            this.maskCtx.globalCompositeOperation = 'destination-out';
        } else if (this.coverType == 'image'){
            var image = new Image(),
                _this = this;
            image.onload = function () {
                _this.maskCtx.drawImage(this, 0, 0);
                _this.maskCtx.globalCompositeOperation = 'destination-out';
            }
            image.src = this.cover;
        }
    },
    init: function (lottery, lotteryType) {
        this.lottery = lottery;
        this.lotteryType = lotteryType || 'image';
        this.drawLottery();
    }
}

window.onload = function () {
    var lottery = new Lottery('lotteryContainer', '#CCC', 'color', 300, 100, drawPercent);
    lottery.init('http://www.baidu.com/img/bdlogo.gif', 'image');
    
    document.getElementById('freshBtn').onclick = function() {
        drawPercentNode.innerHTML = '0%';
        lottery.init(getRandomStr(10), 'text');
    }
    
    var drawPercentNode = document.getElementById('drawPercent');
    
    function drawPercent(percent) {
        drawPercentNode.innerHTML = percent + '%';
    }
}

function getRandomStr(len) {
    var text = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    for( var i=0; i < len; i++ )
        text += possible.charAt(Math.floor(Math.random() * possible.length));
    return text;
}
</script>
</body>
</html>
							

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1175265.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

逆向学习记录(5)刷机

首要前提&#xff1a;手机刷机必须OEM解锁&#xff08;BL解锁&#xff09;&#xff0c;否则不能刷机&#xff01; 1、根据手机机型下载手机系统包&#xff0c;首次登陆网址需要同意协议。然后在右侧选机型&#xff0c;中间就出来各种适合本机型的系统。 下载网址 https://dev…

47基于matlab的水印提取,将水印和载体进行图像融合

基于matlab的水印提取&#xff0c;将水印和载体进行图像融合&#xff0c;成为一体&#xff0c;可对合成图像进行加噪处理&#xff0c;剪切处理&#xff0c;小波压缩处理&#xff0c;旋转处理等操作&#xff0c;最后对合成图像实现水印提取&#xff0c;程序已调通&#xff0c;可…

【AI好好玩02】利用Lama Cleaner本地实现AIGC试玩:擦除对象、替换对象、更换风格等等

目录 一、安装二、擦除功能1. LaMa模型实操实例一&#xff1a;去除路人实操实例二&#xff1a;去水印实操实例三&#xff1a;老照片修复 2. LDM模型3. ZITS模型4. MAT模型5. FcF模型6. Manga模型 三、替换对象功能1. sd1.52. sd23. anything44. realisticVision1.45. 四个模型的…

Tomcat安装配置教程

目录 1、安装tomcat1.1、查看JDK版本1.2、 匹配对应的JDK版本1.3、 下载Tomcat1.3.1、 安装包版&#xff08;推荐&#xff0c;不用配环境&#xff09;1.3.2、 压缩包版 2、 运行Tomcat3、 不能运行问题 1、安装tomcat 1.1、查看JDK版本 由于不同版本tomcat对于jdk的版本有要求…

Mac 下安装golang环境

一、下载安装包 安装包下载地址 下载完成&#xff0c;直接继续----->下一步到结束即可安装成功&#xff1b; 安装成功之后&#xff0c;验证一下&#xff1b; go version二、配置环境变量 终端输入vim ~/.zshrc进入配置文件&#xff0c;输入i进行编辑 打开的不管是空文本…

redis教程 二 redis客户端Jedis使用

文章目录 Redis的Java客户端-JedisJedis快速入门创建工程&#xff1a;引入依赖&#xff1a;建立连接测试&#xff1a;释放资源Jedis连接池创建Jedis的连接池改造原始代码 Redis的Java客户端-SpringDataRedis快速入门导入pom坐标配置文件测试代码 数据序列化器StringRedisTempla…

“第六十一天”

这三个也算一类的&#xff0c;减和加的处理差不多&#xff0c;不过这个题多了限制是被减数大于减数&#xff0c;要是想再完整一点&#xff0c;可以把小于的情况也考虑进去&#xff0c;不过这个我是如果被减数小于减数的话&#xff0c;我就用减数加被减数&#xff0c;然后最后打…

JVM 各个参数详解

在一些规模稍大的应用中&#xff0c;Java虚拟机&#xff08;JVM&#xff09;的内存设置尤为重要&#xff0c;想在项目中取得好的效率&#xff0c;GC&#xff08;垃圾回收&#xff09;的设置是第一步。 PermGen space&#xff1a;全称是Permanent Generation space.就是说是永久…

ActiveMq学习⑤__ActiveMq的Broker

ActiveMq的Broker 是什么&#xff1f; 相当于一个ActiveMq的服务器实例 Broker其实就是实现了用代码的形式启动ActiveMQ将MQ嵌入到Java 代码中&#xff0c;以便随时用随时启动&#xff0c;在用的时候再去启动这样节省了资源&#xff0c;也保证了可靠性。 按照不同的配置文件…

线程的创建、等待、退出

多线程开发在Linux平台上已经有成熟的pthread库支持&#xff0c;所以使用pthread库在编译时要加上-pthread。其设计的多线程开发的基本概念主要包含3点&#xff1a;线程、互斥锁、条件。其中线程操作又分线程的创建、退出、等待三种。互斥锁包含4种操作&#xff0c;分别是创建、…

线程同步——互斥量解锁、解锁

类似与进程间通信信号量的加锁解锁。 对互斥量进行加锁后&#xff0c;任何其他试图在此对互斥量加锁的线程都会被阻塞&#xff0c;直到当前线程释放该互斥锁。如果释放互斥锁时有多个线程被阻塞&#xff0c;所有在该互斥锁上的阻塞线程都会变成可运行状态&#xff0c;第一个变…

《算计》

第一章&#xff1a;机器的诞生 在一个科技高度发达的未来世界&#xff0c;人类社会已经进入了自主机器时代。人们创造出了一种名为“超级自主机器&#xff08;Super Autonomous Machine&#xff0c;简称SAM&#xff09;”的全新型机器&#xff0c;它拥有无限的智慧和学习能力&a…

LeetCode.6 N字形变换

一开始想的是真的创建一个数组 去按照题目所给的要求填入数据 最后输出不为空的数组项 但是不仅时间复杂度高 而且错误频繁出现 最终也没有提交成功 查阅题解后发现数组并不重要 假设我们忽略掉数组中的那些空白项 最终输出的结果就是numRows行的字符串的拼接 string conver…

基于Matlab的yolo算法行人检测系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 # 基于Matlab编写的Yolo算法行人检测系统介绍 基于Matlab编写的Yolo算法行人检测系统是一种用于自动检测图像或视频…

SAP中接口与集成

从进化的角度看SAP中接口和集成的十个概念 - 知乎 SAP比较常用的几个接口方式及比较-SAP技术站 1. 文件接口 基于文件交换的接口是从SAP向第三方系统提供数据的最古老的技术之一。将文本或excel文件推送到特定目录或从应用程序服务器中提取&#xff1b;两种方式都有效。在没有…

[云原生2. ] Kubernetes的简单介绍

文章目录 1. Kubernetes 概述1.1 简介1.2 作用1.3 Kubernetes 的特点1.4 Kubernetes 主要功能 2. Kubernetes 集群架构与组件2.1 Master 组件2.1.1 Kube-apiserver2.1.2 Kube-controller-manager2.1.3 Kube-scheduler 2.2 配置存储中心2.2.1 etcd 2.3. Node 组件2.3.1 Kubelet2…

51单片机-定时计数器

文章目录 前言1 原理2.编程 前言 1 原理 2.编程 定时计算&#xff1a; 50ms501000us 一个机器周期&#xff1a;1.085us 65535 - 501000/1.08546082 故 40082*1.08549998.97 /*定时器1&#xff0c;定时模式 工作模式1 16位计数器&#xff0c; 定时20秒后使能蜂鸣器*/ #include…

MP4视频文件损坏怎么修复?

3-2 作为摄影师&#xff0c;或者在平时有拍摄工作的事情的&#xff0c;比如搞婚庆、搞航拍什么的&#xff0c;有一定的概率会遇到损坏的视频文件&#xff0c;比如相机突然断电、无人机炸机等&#xff0c;有可能会导致保存的MP4文件损坏。 这种文件使用播放器播放的话&#xf…

2023数学建模国赛C题赛后总结

今天国赛的成绩终于出来了&#xff0c;盼星星盼月亮的。之前面试的时候已经把我给推到国奖评委那里去了&#xff0c;可是好可惜&#xff0c;最终以很微小的劣势错失国二。只拿到了广西区的省一。我心里还是很遗憾的&#xff0c;我真的为此准备了很久&#xff0c;虽然当中也有着…

海康Visionmaster-全局脚本:通信设备 ID 获取方法

全局脚本中通信数据接收函数中的 DeviceID 是按照设备管理列表中至上而下、从 0 开始依此增 1&#xff0c;现在这种方法行不通. 每次增加设备列表都会分配唯一的 ID 号&#xff0c;后续全局脚本中判断设备 ID 通过这个唯一 ID 识别&#xff0c;不再从上到下默认排序。