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 ...
随机推荐
- 基于MatConvNet的CNN图像搜索引擎PicSearch
简介 Picsearch是一种基于卷积神经网络特征的图像搜索引擎. Github:https://github.com/willard-yuan/CNN-for-Image-Retrieval Web ...
- (转)Redis持久化的几种方式
radis持久化的几种方式 1.前言 Redis是一种高级key-value数据库.它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富.有字符串,链表,集 合和有序集合.支持在服 ...
- Communication between C++ and Javascript in Qt WebEngine(转载)
Communication between C++ and Javascript in Qt WebEngine admin January 31, 2018 0 As Qt WebKit is re ...
- bzoj 4722 由乃
bzoj 先考虑一种简单的情况,即这个区间是否有相同的数,因为值域大小为1000,那么当区间长度\(>1000\)时,根据鸽巢原理,一定会有两个相同的数,这时候可以直接输出Yuno 进一步的,对 ...
- React前端有钱途吗?《React+Redux前端开发实战》学起来
再不学React就真的跟不上大前端的形式了,目前几乎所有前端的招聘条件都是精通React者优先,看看拉勾网的React薪资,都是15K-20K,这个暑假,必须动起来了. 如果你熟悉JavaScript ...
- 使用CXF开发WebService程序的总结(七):Spring+CXF+Mybatis+Mysql共同打造的服务端示例
通过该demo,可以 熟悉下 spring+cxf+maven+mybatis+mysql等常见后端技术整合 1. 在前面的 父工程 ws_parent 中 添加依赖 由于原来的项目是使用的cxf依赖 ...
- 正确的安装和使用nvm(mac)<转>
前言 目前主流的node版本管理工具有两种,nvm和n.两者差异挺大的,具体分析可以参考一下淘宝FED团队的一篇文章: 管理 node 版本,选择 nvm 还是 n? 总的来说,nvm有点类似于 Py ...
- linux上如何安装postgresql
安装对应的postgresql的yum源 rpm -Uvh https://download.postgresql.org/pub/repos/yum/9.4/redhat/rhel-7-x86_64 ...
- pkg-config --libs libusb-1.0
pkg-config --libs libusb-1.0 pkg-config --libs libusb-1.0 pkg-config --libs libusb-1.0
- 数字转化为汉字,如5->五
//数字转化为汉字 如5-->五-(NSString*)translation:(NSString *)arebic{ NSString *str = arebic; NSArray ...