JS框架_(JQuery.js)模拟刮奖
百度云盘:传送门 密码:6p5q
纯CSS模拟刮奖效果

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<style>
*{
margin: 0;
padding: 0;
} p {
position: fixed;
top: 60%;
left: 0;
right: 0;
text-align: center;
transform: translateY(-50%);
font-size: 40px;
font-weight: 900;
color: white;
text-shadow: 0 0 50px black;
text-transform: capitalize;
font-family: 'Roboto','Helvetica','Arial',sans-serif;
letter-spacing: 5px;
} .box{
margin: 80px;
position: relative;
width: 300px;
height: 180px;
left: 460px;
}
#canvas{
position: absolute;
top: 0;
left: 0;
z-index: 5;
}
.bk{
width: 300px;
height: 180px;
background: #fff;
position: absolute;
top: 0;
left: 0;
text-align: center;
line-height: 180px;
}
#freshBtn{
margin-left: 660px;
user-select: none;
background: #ddd;
width: 80px;
height: 40px;
text-align: center;
line-height: 40px;
}
</style>
<body>
<p>Gary</p>
<div class="box">
<div class="bk">
一等奖
</div>
<canvas id="canvas"></canvas>
</div>
<div id="freshBtn">重置</div>
</body>
<script src="./js/canvas.js"></script>
<script>
var canvas = new canvasInit({
id: 'canvas',
text: '刮开抽奖',
cover: '#1f1f1f',
coverType: 'color',
width: 300,
height: 180,
drawPercentCallback: (num) => {
if(num > 30) {
alert('恭喜获得一等奖')
canvas.fresh() // 重置
}
}
})
</script>
</html>
index.html
class canvasClass {
constructor (id,text,cover,coverType,width,height,drawPercentCallback) {
this.conId = id; /*canvasID */
this.conNode = document.getElementById(this.conId);
this.ctx = this.conNode.getContext('2d');
this.coverText = text;
this.cover = cover; /**图层颜色或图片 */
this.coverType = coverType; /**图层类型(image/color) */
this.width = width;
this.height = height;
this.drawPercentCallback = drawPercentCallback
this.clientRect = null;
this.isMouseDown = false;
}
/**
* 绘制canvas
*/
fillCanvas () {
this.conNode.setAttribute('width', this.width);
this.conNode.setAttribute('height', this.height);
if (this.coverType == 'color') {
this.ctx.save();
this.ctx.fillStyle = this.cover;
this.ctx.fillRect(0, 0, this.width, this.height);
this.ctx.restore();
this.ctx.save();
var fontSize = 30;
this.ctx.font = '30px Arial';
this.ctx.textAlign = 'center';
this.ctx.fillStyle = '#fff';
this.ctx.fillText(this.coverText, this.width/2, this.height/2+fontSize/2);
this.ctx.restore();
this.ctx.globalCompositeOperation = 'destination-out';
} else if (this.coverType == 'image') {
var image = new Image(this.width, this.height)
image.onload = () => {
this.ctx.drawImage(image, 0, 0, this.width, this.height);
}
image.src = this.cover;
}
this.clientRect = this.conNode ? this.conNode.getBoundingClientRect() : null
}
/**
* 事件监听
*/
bindEvent () {
/**移动端检测 */
var device = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
var clickEvt = device ? 'touchstart' : 'mousedown';
var moveEvt = device ? 'touchmove' : 'mousemove';
var x1,y1,x2,y2;
if (!device) {
document.addEventListener('mouseup', (e) => {
this.isMouseDown = false;
})
} else {
document.addEventListener("touchmove", (e) => {
if (this.isMouseDown) {
e.preventDefault();
}
})
document.addEventListener("touchend", (e) => {
this.isMouseDown = false;
})
}
/**添加监听 */
this.conNode.addEventListener(clickEvt, (e) => {
this.isMouseDown = true;
x1 = device ? e.touches[0].offsetX : e.offsetX;
y1 = device ? e.touches[0].offsetY : e.offsetY;
this.drawPoint(x1, y1)
})
this.conNode.addEventListener(moveEvt, (e) => {
if (!device && !this.isMouseDown) {
return false;
}
this.isMouseDown = true;
x2 = device ? e.touches[0].offsetX : e.offsetX;
y2 = device ? e.touches[0].offsetY : e.offsetY;
this.drawPoint(x1, y1, x2, y2)
// console.log(x1,x2,y1,y2)
x1 = x2
y1 = y2
// [x1, y1] = [x2, y2]
})
}
/**
* 抹去, 返回百分比
*/
drawPoint (x1, y1, x2, y2) {
var bar = 20; // 半径
this.ctx.beginPath();
if (x2) {
/**
* 优化绘制路径
*/
var asin = bar*Math.sin(Math.atan((y2-y1)/(x2-x1)));
var acos = bar*Math.cos(Math.atan((y2-y1)/(x2-x1)))
var x3 = x1+asin;
var y3 = y1-acos;
var x4 = x1-asin;
var y4 = y1+acos;
var x5 = x2+asin;
var y5 = y2-acos;
var x6 = x2-asin;
var y6 = y2+acos;
this.ctx.save();
this.ctx.beginPath();
this.ctx.moveTo(x3,y3);
this.ctx.lineTo(x5,y5);
this.ctx.lineTo(x6,y6);
this.ctx.lineTo(x4,y4);
this.ctx.closePath();
this.ctx.clip();
this.ctx.clearRect(0,0,this.width,this.height);
this.ctx.restore();
this.ctx.arc(x2, y2, bar, 0, Math.PI*2, true);
} else {
this.ctx.arc(x1, y1, bar, 0, Math.PI*2, true);
}
this.ctx.fill();
if (this.drawPercentCallback) {
this.drawPercentCallback(this.getTransparentPercent());
}
}
getTransparentPercent () {
var imgData = this.ctx.getImageData(0, 0, this.width, this.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);
}
}
function canvasInit(json) {
var arr = []
for (let item in json) {
arr.push(json[item])
}
this.init = new canvasClass(...arr)
this.init.fillCanvas()
this.init.bindEvent()
var btn = document.querySelector('#freshBtn');
btn.addEventListener('click', (e) => {
this.init.fillCanvas()
});
}
canvasInit.prototype.fresh = function () {
console.log(this.init)
this.init.fillCanvas()
this.init.isMouseDown = false
}
canvas.css
(直接复制就可以使用了O(∩_∩)O~ ES6编写)
=>是es6语法中的arrow function(箭头函数)
举例:
(x) => x + 6
相当于
function(x){
return x + 6;
}
实现过程
CSS
画板.class
class canvasClass {
constructor (id,text,cover,coverType,width,height,drawPercentCallback) {
this.conId = id; /*canvasID */
this.conNode = document.getElementById(this.conId);
this.ctx = this.conNode.getContext('2d');
this.coverText = text;
this.cover = cover; /**图层颜色或图片 */
this.coverType = coverType; /**图层类型(image/color) */
this.width = width;
this.height = height;
this.drawPercentCallback = drawPercentCallback
this.clientRect = null;
this.isMouseDown = false;
}
/**
* 绘制canvas
*/
fillCanvas () {
this.conNode.setAttribute('width', this.width);
this.conNode.setAttribute('height', this.height);
if (this.coverType == 'color') {
this.ctx.save();
this.ctx.fillStyle = this.cover;
this.ctx.fillRect(0, 0, this.width, this.height);
this.ctx.restore();
this.ctx.save();
var fontSize = 30;
this.ctx.font = '30px Arial';
this.ctx.textAlign = 'center';
this.ctx.fillStyle = '#fff';
this.ctx.fillText(this.coverText, this.width/2, this.height/2+fontSize/2);
this.ctx.restore();
this.ctx.globalCompositeOperation = 'destination-out';
} else if (this.coverType == 'image') {
var image = new Image(this.width, this.height)
image.onload = () => {
this.ctx.drawImage(image, 0, 0, this.width, this.height);
}
image.src = this.cover;
}
this.clientRect = this.conNode ? this.conNode.getBoundingClientRect() : null
}
/**
* 事件监听
*/
bindEvent () {
/**移动端检测 */
var device = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
var clickEvt = device ? 'touchstart' : 'mousedown';
var moveEvt = device ? 'touchmove' : 'mousemove';
var x1,y1,x2,y2;
if (!device) {
document.addEventListener('mouseup', (e) => {
this.isMouseDown = false;
})
} else {
document.addEventListener("touchmove", (e) => {
if (this.isMouseDown) {
e.preventDefault();
}
})
document.addEventListener("touchend", (e) => {
this.isMouseDown = false;
})
}
/**添加监听 */
this.conNode.addEventListener(clickEvt, (e) => {
this.isMouseDown = true;
x1 = device ? e.touches[0].offsetX : e.offsetX;
y1 = device ? e.touches[0].offsetY : e.offsetY;
this.drawPoint(x1, y1)
})
this.conNode.addEventListener(moveEvt, (e) => {
if (!device && !this.isMouseDown) {
return false;
}
this.isMouseDown = true;
x2 = device ? e.touches[0].offsetX : e.offsetX;
y2 = device ? e.touches[0].offsetY : e.offsetY;
this.drawPoint(x1, y1, x2, y2)
// console.log(x1,x2,y1,y2)
x1 = x2
y1 = y2
// [x1, y1] = [x2, y2]
})
}
/**
* 抹去, 返回百分比
*/
drawPoint (x1, y1, x2, y2) {
var bar = 20; // 半径
this.ctx.beginPath();
if (x2) {
/**
* 优化绘制路径
*/
var asin = bar*Math.sin(Math.atan((y2-y1)/(x2-x1)));
var acos = bar*Math.cos(Math.atan((y2-y1)/(x2-x1)))
var x3 = x1+asin;
var y3 = y1-acos;
var x4 = x1-asin;
var y4 = y1+acos;
var x5 = x2+asin;
var y5 = y2-acos;
var x6 = x2-asin;
var y6 = y2+acos;
this.ctx.save();
this.ctx.beginPath();
this.ctx.moveTo(x3,y3);
this.ctx.lineTo(x5,y5);
this.ctx.lineTo(x6,y6);
this.ctx.lineTo(x4,y4);
this.ctx.closePath();
this.ctx.clip();
this.ctx.clearRect(0,0,this.width,this.height);
this.ctx.restore();
this.ctx.arc(x2, y2, bar, 0, Math.PI*2, true);
} else {
this.ctx.arc(x1, y1, bar, 0, Math.PI*2, true);
}
this.ctx.fill();
if (this.drawPercentCallback) {
this.drawPercentCallback(this.getTransparentPercent());
}
}
getTransparentPercent () {
var imgData = this.ctx.getImageData(0, 0, this.width, this.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);
}
}
class canvasClass
1、绘制canvas画布
2、添加事件监听
3、刮奖效果
构造函数省略...
1、绘制canvas画布
fillCanvas () {
this.conNode.setAttribute('width', this.width);
this.conNode.setAttribute('height', this.height);
if (this.coverType == 'color') {
this.ctx.save();
this.ctx.fillStyle = this.cover;
this.ctx.fillRect(0, 0, this.width, this.height);
this.ctx.restore();
this.ctx.save();
var fontSize = 30;
this.ctx.font = '30px Arial';
this.ctx.textAlign = 'center';
this.ctx.fillStyle = '#fff';
this.ctx.fillText(this.coverText, this.width/2, this.height/2+fontSize/2);
this.ctx.restore();
this.ctx.globalCompositeOperation = 'destination-out';
} else if (this.coverType == 'image') {
var image = new Image(this.width, this.height)
image.onload = () => {
this.ctx.drawImage(image, 0, 0, this.width, this.height);
}
image.src = this.cover;
}
this.clientRect = this.conNode ? this.conNode.getBoundingClientRect() : null
}
2、添加事件监听
bindEvent () {
/**移动端检测 */
var device = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
var clickEvt = device ? 'touchstart' : 'mousedown';
var moveEvt = device ? 'touchmove' : 'mousemove';
var x1,y1,x2,y2;
if (!device) {
document.addEventListener('mouseup', (e) => {
this.isMouseDown = false;
})
} else {
document.addEventListener("touchmove", (e) => {
if (this.isMouseDown) {
e.preventDefault();
}
})
document.addEventListener("touchend", (e) => {
this.isMouseDown = false;
})
}
/**添加监听 */
this.conNode.addEventListener(clickEvt, (e) => {
this.isMouseDown = true;
x1 = device ? e.touches[0].offsetX : e.offsetX;
y1 = device ? e.touches[0].offsetY : e.offsetY;
this.drawPoint(x1, y1)
})
this.conNode.addEventListener(moveEvt, (e) => {
if (!device && !this.isMouseDown) {
return false;
}
this.isMouseDown = true;
x2 = device ? e.touches[0].offsetX : e.offsetX;
y2 = device ? e.touches[0].offsetY : e.offsetY;
this.drawPoint(x1, y1, x2, y2)
// console.log(x1,x2,y1,y2)
x1 = x2
y1 = y2
// [x1, y1] = [x2, y2]
})
}
3、刮奖效果
drawPoint (x1, y1, x2, y2) {
var bar = 20; // 半径
this.ctx.beginPath();
if (x2) {
/**
* 优化绘制路径
*/
var asin = bar*Math.sin(Math.atan((y2-y1)/(x2-x1)));
var acos = bar*Math.cos(Math.atan((y2-y1)/(x2-x1)))
var x3 = x1+asin;
var y3 = y1-acos;
var x4 = x1-asin;
var y4 = y1+acos;
var x5 = x2+asin;
var y5 = y2-acos;
var x6 = x2-asin;
var y6 = y2+acos;
this.ctx.save();
this.ctx.beginPath();
this.ctx.moveTo(x3,y3);
this.ctx.lineTo(x5,y5);
this.ctx.lineTo(x6,y6);
this.ctx.lineTo(x4,y4);
this.ctx.closePath();
this.ctx.clip();
this.ctx.clearRect(0,0,this.width,this.height);
this.ctx.restore();
this.ctx.arc(x2, y2, bar, 0, Math.PI*2, true);
} else {
this.ctx.arc(x1, y1, bar, 0, Math.PI*2, true);
}
this.ctx.fill();
if (this.drawPercentCallback) {
this.drawPercentCallback(this.getTransparentPercent());
}
}
初始化canvas.class画布
function canvasInit(json) {
var arr = []
for (let item in json) {
arr.push(json[item])
}
this.init = new canvasClass(...arr)
this.init.fillCanvas()
this.init.bindEvent()
var btn = document.querySelector('#freshBtn');
btn.addEventListener('click', (e) => {
this.init.fillCanvas()
});
}
按钮
#freshBtn{
margin-left: 660px;
user-select: none;
background: #ddd;
width: 80px;
height: 40px;
text-align: center;
line-height: 40px;
}
刮奖区域
.box{
margin: 80px;
position: relative;
width: 300px;
height: 180px;
left: 460px;
}
DOM
设置文档内容和显示文本
<div class="box">
<div class="bk">
一等奖
</div>
<canvas id="canvas"></canvas>
</div>
<div id="freshBtn">重置</div>
模拟抽奖效果时bk中文字可以用随机
给canvas.class画布传参
<script>
var canvas = new canvasInit({
id: 'canvas',
text: '刮开抽奖',
cover: '#1f1f1f',
coverType: 'color',
width: 300,
height: 180,
drawPercentCallback: (num) => {
if(num > 30) {
alert('恭喜获得一等奖')
canvas.fresh() // 重置
}
}
})
</script>
JS框架_(JQuery.js)模拟刮奖的更多相关文章
- JS框架_(JQuery.js)绚丽的3D星空动画
百度云盘: 传送门 密码:8ft8 绚丽的3D星空动画效果(纯CSS) (3D星空动画可以用作网页背景,Gary为文本文字) <!doctype html> <html lang=& ...
- JS框架_(JQuery.js)圆形多选菜单选项
百度云盘 传送门 密码:zb1c 圆形多选菜单选项效果: <!DOCTYPE html> <html lang="en" > <head> &l ...
- JS框架_(JQuery.js)Tooltip弹出式按钮插件
百度云盘 传送门 密码:7eh5 弹出式按钮效果 <!DOCTYPE html> <html > <head> <meta charset="UTF ...
- JS框架_(JQuery.js)夜晚天空满天星星闪烁动画
百度云盘 传送门 密码:xftr 满天星星闪烁动画效果: (可用星空动画来作为页面背景,白色文字改为文章或者其他的O(∩_∩)O) <!doctype html> <html> ...
- JS框架_(JQuery.js)文章全屏动画切换
百度云盘 传送门 密码:anap 文章全屏动画切换效果 <!doctype html> <html lang="zh"> <head> < ...
- JS框架_(JQuery.js)动画效果鼠标跟随
百度云盘 传送门 密码 :4n9u 火狐浏览器上纯CSS_动画效果鼠标跟随效果: (作者:lily_lcj 传送门) <!DOCTYPE html PUBLIC "-//W3C//DT ...
- JS框架_(JQuery.js)点赞按钮动画
百度云盘 传送门 密码: 0ihy 点赞按钮动画效果: (点击一次随机生成一颗小爱心,作为点赞动画~) <!doctype html> <html lang="en&quo ...
- JS框架_(JQuery.js)图片相册掀开切换效果
百度云盘 传送门 密码:y0dk 图片掀开切换效果: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&quo ...
- JS框架_(JQuery.js)上传进度条
百度云盘 传送门 密码: 1pou 纯CSS上传进度条效果: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN ...
随机推荐
- # 「NOIP2010」关押罪犯(二分图染色+二分答案)
「NOIP2010」关押罪犯(二分图染色+二分答案) 洛谷 P1525 描述:n个罪犯(1-N),两个罪犯之间的仇恨值为c,m对仇恨值,求怎么分配使得两件监狱的最大仇恨值最小. 思路:使最大xxx最小 ...
- [Nest] 03.nest之提供者 provider
提供者 provider 提供程序是 Nest 的一个基本概念.许多基本的 Nest 类可能被视为提供者 - service,repository, factory, helper 等等. 他们都可以 ...
- numpy:np.random.seed()
np.random.seed()函数可以保证生成的随机数具有可预测性. 可以使多次生成的随机数相同 1.如果使用相同的seed( )值,则每次生成的随即数都相同: 2.如果不设置这个值,则系统根据时间 ...
- golang(4):函数 & 数组 & 切片 & map & 锁
内置函数 // 1. close:主要用来关闭channel // 2. len:用来求长度,比如string.array.slice.map.channel // 3. new:用来分配内存,主要用 ...
- css动画之旋转翻牌效果
1.我们先设置两个盒子大小,颜色等等,然后定位重叠在一起,最后再进行动画设置 例子如下: <style> .box { height: 300px; width: 300px; posit ...
- Vue初始化一个项目
@1 npm install -g @vue/cli-init vue init webpack projectName @2 cnpm install -g @vue/cli vue create ...
- 多Y轴,下拉框渲染,相同类型不同数据
放上json文件: { "2017年3月": { "outKou": "5525.86", "inKou": " ...
- springboot启动端口占用问题,报错org.apache.catalina.LifecycleException: Protocol handler start failed
解决办法,找到被占用的端口
- Navicat连接Mysql11.1.13出现1251错误
打开Navicat软件,单击左上角[连接]按钮,选择mysql,弹出新建连接,输入相关信息,单击[连接测试],报1251的错误,如下图所示: 根因分析: mysql8 之前的版本中加密规则是mysql ...
- python、第三篇:表相关操作
一 存储引擎介绍 存储引擎即表类型,mysql根据不同的表类型会有不同的处理机制 详见:https://www.cnblogs.com/Forever-x/p/11317479.html 二 表介绍 ...