百度云盘:传送门  密码: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)模拟刮奖的更多相关文章

  1. JS框架_(JQuery.js)绚丽的3D星空动画

    百度云盘: 传送门 密码:8ft8 绚丽的3D星空动画效果(纯CSS) (3D星空动画可以用作网页背景,Gary为文本文字) <!doctype html> <html lang=& ...

  2. JS框架_(JQuery.js)圆形多选菜单选项

    百度云盘 传送门 密码:zb1c 圆形多选菜单选项效果: <!DOCTYPE html> <html lang="en" > <head> &l ...

  3. JS框架_(JQuery.js)Tooltip弹出式按钮插件

    百度云盘 传送门 密码:7eh5 弹出式按钮效果 <!DOCTYPE html> <html > <head> <meta charset="UTF ...

  4. JS框架_(JQuery.js)夜晚天空满天星星闪烁动画

    百度云盘 传送门 密码:xftr 满天星星闪烁动画效果: (可用星空动画来作为页面背景,白色文字改为文章或者其他的O(∩_∩)O) <!doctype html> <html> ...

  5. JS框架_(JQuery.js)文章全屏动画切换

    百度云盘 传送门 密码:anap 文章全屏动画切换效果 <!doctype html> <html lang="zh"> <head> < ...

  6. JS框架_(JQuery.js)动画效果鼠标跟随

    百度云盘 传送门 密码 :4n9u 火狐浏览器上纯CSS_动画效果鼠标跟随效果: (作者:lily_lcj 传送门) <!DOCTYPE html PUBLIC "-//W3C//DT ...

  7. JS框架_(JQuery.js)点赞按钮动画

    百度云盘 传送门 密码: 0ihy 点赞按钮动画效果: (点击一次随机生成一颗小爱心,作为点赞动画~) <!doctype html> <html lang="en&quo ...

  8. JS框架_(JQuery.js)图片相册掀开切换效果

    百度云盘 传送门 密码:y0dk 图片掀开切换效果: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&quo ...

  9. JS框架_(JQuery.js)上传进度条

    百度云盘 传送门 密码: 1pou 纯CSS上传进度条效果: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN ...

随机推荐

  1. 双元素非递增(容斥)--Number Of Permutations Educational Codeforces Round 71 (Rated for Div. 2)

    题意:https://codeforc.es/contest/1207/problem/D n个元素,每个元素有a.b两个属性,问你n个元素的a序列和b序列有多少种排序方法使他们不同时非递减(不同时g ...

  2. JavaScript处理股票数据

    1, 先使用Ajax发送异步请求到:http://hq.sinajs.cn/list=s_sh000001 2, 然后用[,]切割成数组https://www.w3school.com.cn/js/j ...

  3. expect批量分发密钥对

    vim shell.exp #!/usr/bin/expect set timeout 10 set hostname [lindex $argv 0] set username [lindex $a ...

  4. 26 Python模块之paramiko

    paramiko模块提供了ssh及sft进行远程登录服务器执行命令和上传下载文件的功能.这是一个第三方的软件包,使用之前需要安装. 1. 基于用户名和密码的sshclient方式登录 #创建一个ssh ...

  5. openCV3 Python编译指南

    这里主要对openCV官网的<Installation in Linux>文档进行了翻译和解释 原文见:https://docs.opencv.org/3.4.1/doc/tutorial ...

  6. python视频学习笔记5(高级变量的类型)

    知识点回顾: Python 中数据类型可以分为 **数字型** 和 **非数字型*** 数字型 * 整型 (`int`) * 浮点型(`float`) * 布尔型(`bool`) * 真 `True` ...

  7. 可靠的TCP连接为何是三次握手和四次挥手

    首先,咱们先来熟悉下经典的tcp/ip模型. tcp/ip 模型为了方便使用,将osi七层模型划分成了四层,分别为网络接口层,网络层,传输层,应用层. 他们作用分别为: 1)网络接口层:主要作用是将i ...

  8. 使用Spring Mail发送QQ邮件

    一.邮箱设置 QQ邮箱设置:http://service.mail.qq.com/cgi-bin/help?id=28, 下面这些服务需要开启(需要设置邮箱独立密码): 二.applicationCo ...

  9. Function HDU - 6546 (数学,贪心)

    wls 有 n 个二次函数 Fi(x) = aix2 + bix + ci (1 ≤ i ≤ n). 现在他想在∑ni=1xi = m 且 x 为正整数的条件下求∑ni=1Fi(xi)的最小值. 请求 ...

  10. jenkins之Extended Choice Parameter多选插件