提交 49501ba5 编写于 作者: 杨龙伟

init project

上级 9df27996
run = "npm i && npm run dev" run = "cd lottery && cd server && npm i && cd ../product && npm i && npm run build && npm run start"
language = "node" language = "node"
[env] [env]
......
#npm
node_modules/
temp.json
error.json
\ No newline at end of file
# Use the official Node.js 16 image as base image
FROM node:16.14.0-buster
# Upgrade npm to the latest version
RUN npm install -g npm@9.6.2
# Set the author of the Dockerfile
LABEL maintainer="YIN"
# Add the application source code to the container
ADD lottery.tar.gz /
# Set the working directory to the root directory of the application
WORKDIR /lottery
# Set the ownership of the application directory to root
RUN chown -R root /lottery \
# Remove the line that opens the default browser when starting the server
&& sed -i '/openBrowser/ d' ./server/server.js \
# Install dependencies for the server and product directories
&& cd server && npm install \
&& cd ../product && npm install \
# Build the application
&& npm run build
# Expose port 8080 to the outside world
EXPOSE 8080
# Set the working directory to the product directory
WORKDIR /lottery/product
# Start the server
CMD ["npm", "run", "serve"]
MIT License
Copyright (c) 2017 Pavel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# 演示示例
点击访问: [https://inscode-lottery.inscode.cc](inscode-lottery)
# 源码
> 项目来源于: [https://moshang-xc.github.io/lottery/](https://moshang-xc.github.io/lottery/)
本项目基于源码做以下修改
> - 增加InsCode一键部署脚本
> - 增加一键全屏
> - 屏蔽号牌
立即体验:
# 抽奖程序
年会抽奖程序,3D 球体抽奖,支持奖品信息配置,参与抽奖人员信息`Excel`导入,抽奖结果`Excel`导出
如果该程序对你有帮助😎😎😎,希望给个⭐**star**⭐喔。😘😘😘😍🥰🎉🎈🎃
> 立即体验一下: [https://moshang-xc.github.io/lottery/](https://moshang-xc.github.io/lottery/)
## 技术
技术:Node + Express + Three.js
后台通过`Express`实现
前端抽奖界面通过`Three.js`实现 3D 抽奖球,引用了`Three.js`的官方 3D 示例
## 功能描述:
1. 可将抽奖结果进行保存实时下载到 excel 中🎉
2. 已抽取人员不在参与抽取,抽中的人员不在现场可以重新抽取🎁
3. 刷新或者关掉服务器,会保存当前已抽取的数据,不会进行数据重置,只有点击界面上的重置按钮,才能重置抽奖数据🧧
4. 每次抽取的奖品数目可配置🎈
5. 抽取完所有奖品后还可以继续抽取特别奖(例如:现在抽取红包,追加的奖品等),此时默认一次抽取一个🧨
## 预览
![lottery.gif](https://raw.githubusercontent.com/moshang-xc/blog/master/share/lottery.gif)
![index.jpg](https://raw.githubusercontent.com/moshang-xc/blog/master/share/index.jpg)
![start.jpg](https://raw.githubusercontent.com/moshang-xc/blog/master/share/start.jpg)
![end.jpg](https://raw.githubusercontent.com/moshang-xc/blog/master/share/end.jpg)
## 安装
```
git clone https://github.com/moshang-xc/lottery.git
cd lottery
# 服务端插件安装
cd server
npm install
# 前端插件安装
cd ../product
npm install
# 打包
npm run build
# 运行
npm run serve
# 开发调试
npm run dev
```
## 目录结构
```
Lottery
├── product
│ ├── src
│ │ ├── lottery
│ │ │ └── index.js
│ │ ├── lib
│ │ ├── img
│ │ ├── css
│ │ └── data
│ ├── package.json
│ └── webpack.config.js
├── server
│ ├── config.js
│ ├── server.js
│ └── package.js
```
> 1. product 为前端页面目录
> 2. package.josn web 项目配置文件
> 3. webpack.config.js 打包配置文件
> 4. server 为服务器目录
> 5. config 为奖品信息的配置文件
## 配置信息
### 抽奖用户信息配置
抽奖用户信息在**`server/data/user.xlsx`**文件中,按文件格式进行填充,不能修改文件名和列头
### 奖品信息配置
奖品的配置信息填写在**server/config.js**文件中,不能修改文件名。
**其中奖品 prizes 的配置描述如下:**
| 参数 | 值类型 | 描述 |
| ----- | ------ | ------------------------------------------------------------ |
| type | Number | 奖品类型,唯一标识,0 是默认特别奖的占位符,其它奖品不可使用 |
| count | Number | 奖品数量 |
| text | String | 奖项名称 |
| title | String | 奖品描述 |
| img | String | 奖品的图片地址,图片在**img**目录下 |
```js
// 奖品信息,第一项为预留项不可修改,其他项可根据需要修改
let prizes = [{
type: 0,
count: 1000,
title: "",
text: "特别奖"
},
{
type: 1,
count: 2,
text: "特等奖",
title: "神秘大礼",
img: "../img/secrit.jpg"
},
{
type: 2,
count: 5,
text: "一等奖",
title: "Mac Pro",
img: "../img/mbp.jpg"
}
...
];
```
### 奖品每次抽取个数配置
**EACH_COUNT**用于配置每次的抽奖个数,与 prizes 奖品一一对应,例如上面的奖品配置对应的抽奖个数配置如下:
```js
const EACH_COUNT = [1, 1, 5];
```
如上配置,表示一次抽取的奖品个数顺序为:特别奖每次抽一个,特等奖每次抽一个,一等奖每次抽五个
### 企业标识配置
该标识用于显示在抽奖卡片上。
```js
const COMPANY = "MoShang";
```
## Docker部署方案
### 概述
该项目现在支持使用Docker进行部署。Docker是一个轻量级的容器化平台,可以让您快速地部署、测试和运行应用程序。本文档将向您介绍如何使用Docker部署该项目。
### 系统要求
在您开始使用Docker部署该项目之前,您需要确保已经安装了以下软件:
- Docker(请参阅Docker的官方文档以获取安装说明)
- Docker Compose
### 安装
1. 下载并解压该项目的源代码。
2. 进入解压后的项目目录。
3. 执行以下命令以构建Docker镜像:
```
./build.sh [TAG]
```
这将使用Dockerfile构建一个名为`lottery:[TAG]`的Docker镜像。如果未指定标签,则默认使用`latest`标签。
4. 执行以下命令以在本地运行容器:
```
./dev.sh [TAG]
```
这将启动容器并将应用程序部署在Docker容器中。您可以在本地进行测试,确保一切正常。请注意,容器内部的应用程序将会监听8888端口和443端口。
5. 执行以下命令以将Docker镜像标记并推送到远程Docker仓库:
```
./tagpush.sh [TAG]
```
这将为Docker镜像打上标签并将其推送到远程Docker仓库,如果要使用docker官方的hub请先在https://hub.docker.com/新建自己的repo,然后将文件中的用户名改为自己。请注意,`[TAG]`应替换为您要使用的标签名称。
6. 确保有一个名为`docker-compose.yml`的文件,并添加以下内容:
```
version: '3.8'
volumes:
lottery_log:
services:
lottery:
container_name: lottery
expose:
- 8888
ports:
- "28458:8888"
- "443:443"
volumes:
- "lottery_log:/var/log"
image: "panda1024/lottery:[TAG]"
restart: always
```
请注意,`[TAG]`应替换为您推送到Docker仓库的镜像名称。
7. 在服务器上的项目目录中运行以下命令以使用Docker Compose部署应用程序:
```
docker-compose up -d
```
​ 这将启动一个Docker Compose堆栈,并将该项目部署在其中。请注意,此处将容器的8888端口和443端口映射 到了服务器上的8888端口和443端口。如果您希望使用其他端口,请相应地更改`docker-compose.yml`文件。
## License
MIT
TAG=${1:-latest}
rm -f lottery.tar.gz
tar -czvf lottery.tar.gz ../lottery/
docker build -t lottery:$TAG -f ./Dockerfile .
TAG=${1:-latest}
docker run --rm -it \
-p 5003:8888 \
-p 443:443 \
-v "$(pwd)"/server/data:/lottery/server/data/ \
lottery:$TAG
version: '3.8'
volumes:
lottery_log:
services:
lottery:
container_name: lottery
expose:
- 28458
ports:
- "28458:8888"
volumes:
- "lottery_log:/var/log"
image: "panda1024/lottery:v0.3"
restart: always
{
"name": "lucky",
"version": "1.0.0",
"description": "抽奖",
"main": "index.js",
"scripts": {
"start": "cd dist && node ../../server/index.js 8888",
"serve": "npm run start",
"build": "export NODE_OPTIONS=--openssl-legacy-provider && webpack --mode=production --progress --colors",
"dev": "webpack-dev-server --config webpack.dev.js --mode=development --progress --colors"
},
"author": "moshang",
"license": "ISC",
"devDependencies": {
"autoprefixer": "^8.1.0",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.3",
"babel-preset-es2015": "^6.24.1",
"babel-preset-es2015-loose": "^8.0.0",
"clean-webpack-plugin": "^0.1.19",
"copy-webpack-plugin": "^4.5.0",
"cross-env": "^6.0.3",
"css-loader": "^0.28.10",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.0.4",
"postcss-loader": "^2.1.1",
"style-loader": "^0.20.2",
"url-loader": "^1.0.1",
"webpack": "^4.41.4",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.10.1",
"webpack-merge": "^4.2.2"
},
"dependencies": {}
}
module.exports = {
plugins: [
require('autoprefixer')
]
}
\ No newline at end of file
@charset "UTF-8";
/*!
* animate.css -http://daneden.me/animate
* Version - 3.5.2
* Licensed under the MIT license - http://opensource.org/licenses/MIT
*
* Copyright (c) 2017 Daniel Eden
*/
.animated{animation-duration:1s;animation-fill-mode:both}.animated.infinite{animation-iteration-count:infinite}.animated.hinge{animation-duration:2s}.animated.bounceIn,.animated.bounceOut,.animated.flipOutX,.animated.flipOutY{animation-duration:.75s}@keyframes bounce{0%,20%,53%,80%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1);transform:translateZ(0)}40%,43%{animation-timing-function:cubic-bezier(.755,.05,.855,.06);transform:translate3d(0,-30px,0)}70%{animation-timing-function:cubic-bezier(.755,.05,.855,.06);transform:translate3d(0,-15px,0)}90%{transform:translate3d(0,-4px,0)}}.bounce{animation-name:bounce;transform-origin:center bottom}@keyframes flash{0%,50%,to{opacity:1}25%,75%{opacity:0}}.flash{animation-name:flash}@keyframes pulse{0%{transform:scaleX(1)}50%{transform:scale3d(1.05,1.05,1.05)}to{transform:scaleX(1)}}.pulse{animation-name:pulse}@keyframes rubberBand{0%{transform:scaleX(1)}30%{transform:scale3d(1.25,.75,1)}40%{transform:scale3d(.75,1.25,1)}50%{transform:scale3d(1.15,.85,1)}65%{transform:scale3d(.95,1.05,1)}75%{transform:scale3d(1.05,.95,1)}to{transform:scaleX(1)}}.rubberBand{animation-name:rubberBand}@keyframes shake{0%,to{transform:translateZ(0)}10%,30%,50%,70%,90%{transform:translate3d(-10px,0,0)}20%,40%,60%,80%{transform:translate3d(10px,0,0)}}.shake{animation-name:shake}@keyframes headShake{0%{transform:translateX(0)}6.5%{transform:translateX(-6px) rotateY(-9deg)}18.5%{transform:translateX(5px) rotateY(7deg)}31.5%{transform:translateX(-3px) rotateY(-5deg)}43.5%{transform:translateX(2px) rotateY(3deg)}50%{transform:translateX(0)}}.headShake{animation-timing-function:ease-in-out;animation-name:headShake}@keyframes swing{20%{transform:rotate(15deg)}40%{transform:rotate(-10deg)}60%{transform:rotate(5deg)}80%{transform:rotate(-5deg)}to{transform:rotate(0deg)}}.swing{transform-origin:top center;animation-name:swing}@keyframes tada{0%{transform:scaleX(1)}10%,20%{transform:scale3d(.9,.9,.9) rotate(-3deg)}30%,50%,70%,90%{transform:scale3d(1.1,1.1,1.1) rotate(3deg)}40%,60%,80%{transform:scale3d(1.1,1.1,1.1) rotate(-3deg)}to{transform:scaleX(1)}}.tada{animation-name:tada}@keyframes wobble{0%{transform:none}15%{transform:translate3d(-25%,0,0) rotate(-5deg)}30%{transform:translate3d(20%,0,0) rotate(3deg)}45%{transform:translate3d(-15%,0,0) rotate(-3deg)}60%{transform:translate3d(10%,0,0) rotate(2deg)}75%{transform:translate3d(-5%,0,0) rotate(-1deg)}to{transform:none}}.wobble{animation-name:wobble}@keyframes jello{0%,11.1%,to{transform:none}22.2%{transform:skewX(-12.5deg) skewY(-12.5deg)}33.3%{transform:skewX(6.25deg) skewY(6.25deg)}44.4%{transform:skewX(-3.125deg) skewY(-3.125deg)}55.5%{transform:skewX(1.5625deg) skewY(1.5625deg)}66.6%{transform:skewX(-.78125deg) skewY(-.78125deg)}77.7%{transform:skewX(.390625deg) skewY(.390625deg)}88.8%{transform:skewX(-.1953125deg) skewY(-.1953125deg)}}.jello{animation-name:jello;transform-origin:center}@keyframes bounceIn{0%,20%,40%,60%,80%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:scale3d(.3,.3,.3)}20%{transform:scale3d(1.1,1.1,1.1)}40%{transform:scale3d(.9,.9,.9)}60%{opacity:1;transform:scale3d(1.03,1.03,1.03)}80%{transform:scale3d(.97,.97,.97)}to{opacity:1;transform:scaleX(1)}}.bounceIn{animation-name:bounceIn}@keyframes bounceInDown{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(0,-3000px,0)}60%{opacity:1;transform:translate3d(0,25px,0)}75%{transform:translate3d(0,-10px,0)}90%{transform:translate3d(0,5px,0)}to{transform:none}}.bounceInDown{animation-name:bounceInDown}@keyframes bounceInLeft{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(-3000px,0,0)}60%{opacity:1;transform:translate3d(25px,0,0)}75%{transform:translate3d(-10px,0,0)}90%{transform:translate3d(5px,0,0)}to{transform:none}}.bounceInLeft{animation-name:bounceInLeft}@keyframes bounceInRight{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(3000px,0,0)}60%{opacity:1;transform:translate3d(-25px,0,0)}75%{transform:translate3d(10px,0,0)}90%{transform:translate3d(-5px,0,0)}to{transform:none}}.bounceInRight{animation-name:bounceInRight}@keyframes bounceInUp{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(0,3000px,0)}60%{opacity:1;transform:translate3d(0,-20px,0)}75%{transform:translate3d(0,10px,0)}90%{transform:translate3d(0,-5px,0)}to{transform:translateZ(0)}}.bounceInUp{animation-name:bounceInUp}@keyframes bounceOut{20%{transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;transform:scale3d(1.1,1.1,1.1)}to{opacity:0;transform:scale3d(.3,.3,.3)}}.bounceOut{animation-name:bounceOut}@keyframes bounceOutDown{20%{transform:translate3d(0,10px,0)}40%,45%{opacity:1;transform:translate3d(0,-20px,0)}to{opacity:0;transform:translate3d(0,2000px,0)}}.bounceOutDown{animation-name:bounceOutDown}@keyframes bounceOutLeft{20%{opacity:1;transform:translate3d(20px,0,0)}to{opacity:0;transform:translate3d(-2000px,0,0)}}.bounceOutLeft{animation-name:bounceOutLeft}@keyframes bounceOutRight{20%{opacity:1;transform:translate3d(-20px,0,0)}to{opacity:0;transform:translate3d(2000px,0,0)}}.bounceOutRight{animation-name:bounceOutRight}@keyframes bounceOutUp{20%{transform:translate3d(0,-10px,0)}40%,45%{opacity:1;transform:translate3d(0,20px,0)}to{opacity:0;transform:translate3d(0,-2000px,0)}}.bounceOutUp{animation-name:bounceOutUp}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.fadeIn{animation-name:fadeIn}@keyframes fadeInDown{0%{opacity:0;transform:translate3d(0,-100%,0)}to{opacity:1;transform:none}}.fadeInDown{animation-name:fadeInDown}@keyframes fadeInDownBig{0%{opacity:0;transform:translate3d(0,-2000px,0)}to{opacity:1;transform:none}}.fadeInDownBig{animation-name:fadeInDownBig}@keyframes fadeInLeft{0%{opacity:0;transform:translate3d(-100%,0,0)}to{opacity:1;transform:none}}.fadeInLeft{animation-name:fadeInLeft}@keyframes fadeInLeftBig{0%{opacity:0;transform:translate3d(-2000px,0,0)}to{opacity:1;transform:none}}.fadeInLeftBig{animation-name:fadeInLeftBig}@keyframes fadeInRight{0%{opacity:0;transform:translate3d(100%,0,0)}to{opacity:1;transform:none}}.fadeInRight{animation-name:fadeInRight}@keyframes fadeInRightBig{0%{opacity:0;transform:translate3d(2000px,0,0)}to{opacity:1;transform:none}}.fadeInRightBig{animation-name:fadeInRightBig}@keyframes fadeInUp{0%{opacity:0;transform:translate3d(0,100%,0)}to{opacity:1;transform:none}}.fadeInUp{animation-name:fadeInUp}@keyframes fadeInUpBig{0%{opacity:0;transform:translate3d(0,2000px,0)}to{opacity:1;transform:none}}.fadeInUpBig{animation-name:fadeInUpBig}@keyframes fadeOut{0%{opacity:1}to{opacity:0}}.fadeOut{animation-name:fadeOut}@keyframes fadeOutDown{0%{opacity:1}to{opacity:0;transform:translate3d(0,100%,0)}}.fadeOutDown{animation-name:fadeOutDown}@keyframes fadeOutDownBig{0%{opacity:1}to{opacity:0;transform:translate3d(0,2000px,0)}}.fadeOutDownBig{animation-name:fadeOutDownBig}@keyframes fadeOutLeft{0%{opacity:1}to{opacity:0;transform:translate3d(-100%,0,0)}}.fadeOutLeft{animation-name:fadeOutLeft}@keyframes fadeOutLeftBig{0%{opacity:1}to{opacity:0;transform:translate3d(-2000px,0,0)}}.fadeOutLeftBig{animation-name:fadeOutLeftBig}@keyframes fadeOutRight{0%{opacity:1}to{opacity:0;transform:translate3d(100%,0,0)}}.fadeOutRight{animation-name:fadeOutRight}@keyframes fadeOutRightBig{0%{opacity:1}to{opacity:0;transform:translate3d(2000px,0,0)}}.fadeOutRightBig{animation-name:fadeOutRightBig}@keyframes fadeOutUp{0%{opacity:1}to{opacity:0;transform:translate3d(0,-100%,0)}}.fadeOutUp{animation-name:fadeOutUp}@keyframes fadeOutUpBig{0%{opacity:1}to{opacity:0;transform:translate3d(0,-2000px,0)}}.fadeOutUpBig{animation-name:fadeOutUpBig}@keyframes flip{0%{transform:perspective(400px) rotateY(-1turn);animation-timing-function:ease-out}40%{transform:perspective(400px) translateZ(150px) rotateY(-190deg);animation-timing-function:ease-out}50%{transform:perspective(400px) translateZ(150px) rotateY(-170deg);animation-timing-function:ease-in}80%{transform:perspective(400px) scale3d(.95,.95,.95);animation-timing-function:ease-in}to{transform:perspective(400px);animation-timing-function:ease-in}}.animated.flip{-webkit-backface-visibility:visible;backface-visibility:visible;animation-name:flip}@keyframes flipInX{0%{transform:perspective(400px) rotateX(90deg);animation-timing-function:ease-in;opacity:0}40%{transform:perspective(400px) rotateX(-20deg);animation-timing-function:ease-in}60%{transform:perspective(400px) rotateX(10deg);opacity:1}80%{transform:perspective(400px) rotateX(-5deg)}to{transform:perspective(400px)}}.flipInX{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;animation-name:flipInX}@keyframes flipInY{0%{transform:perspective(400px) rotateY(90deg);animation-timing-function:ease-in;opacity:0}40%{transform:perspective(400px) rotateY(-20deg);animation-timing-function:ease-in}60%{transform:perspective(400px) rotateY(10deg);opacity:1}80%{transform:perspective(400px) rotateY(-5deg)}to{transform:perspective(400px)}}.flipInY{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;animation-name:flipInY}@keyframes flipOutX{0%{transform:perspective(400px)}30%{transform:perspective(400px) rotateX(-20deg);opacity:1}to{transform:perspective(400px) rotateX(90deg);opacity:0}}.flipOutX{animation-name:flipOutX;-webkit-backface-visibility:visible!important;backface-visibility:visible!important}@keyframes flipOutY{0%{transform:perspective(400px)}30%{transform:perspective(400px) rotateY(-15deg);opacity:1}to{transform:perspective(400px) rotateY(90deg);opacity:0}}.flipOutY{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;animation-name:flipOutY}@keyframes lightSpeedIn{0%{transform:translate3d(100%,0,0) skewX(-30deg);opacity:0}60%{transform:skewX(20deg);opacity:1}80%{transform:skewX(-5deg);opacity:1}to{transform:none;opacity:1}}.lightSpeedIn{animation-name:lightSpeedIn;animation-timing-function:ease-out}@keyframes lightSpeedOut{0%{opacity:1}to{transform:translate3d(100%,0,0) skewX(30deg);opacity:0}}.lightSpeedOut{animation-name:lightSpeedOut;animation-timing-function:ease-in}@keyframes rotateIn{0%{transform-origin:center;transform:rotate(-200deg);opacity:0}to{transform-origin:center;transform:none;opacity:1}}.rotateIn{animation-name:rotateIn}@keyframes rotateInDownLeft{0%{transform-origin:left bottom;transform:rotate(-45deg);opacity:0}to{transform-origin:left bottom;transform:none;opacity:1}}.rotateInDownLeft{animation-name:rotateInDownLeft}@keyframes rotateInDownRight{0%{transform-origin:right bottom;transform:rotate(45deg);opacity:0}to{transform-origin:right bottom;transform:none;opacity:1}}.rotateInDownRight{animation-name:rotateInDownRight}@keyframes rotateInUpLeft{0%{transform-origin:left bottom;transform:rotate(45deg);opacity:0}to{transform-origin:left bottom;transform:none;opacity:1}}.rotateInUpLeft{animation-name:rotateInUpLeft}@keyframes rotateInUpRight{0%{transform-origin:right bottom;transform:rotate(-90deg);opacity:0}to{transform-origin:right bottom;transform:none;opacity:1}}.rotateInUpRight{animation-name:rotateInUpRight}@keyframes rotateOut{0%{transform-origin:center;opacity:1}to{transform-origin:center;transform:rotate(200deg);opacity:0}}.rotateOut{animation-name:rotateOut}@keyframes rotateOutDownLeft{0%{transform-origin:left bottom;opacity:1}to{transform-origin:left bottom;transform:rotate(45deg);opacity:0}}.rotateOutDownLeft{animation-name:rotateOutDownLeft}@keyframes rotateOutDownRight{0%{transform-origin:right bottom;opacity:1}to{transform-origin:right bottom;transform:rotate(-45deg);opacity:0}}.rotateOutDownRight{animation-name:rotateOutDownRight}@keyframes rotateOutUpLeft{0%{transform-origin:left bottom;opacity:1}to{transform-origin:left bottom;transform:rotate(-45deg);opacity:0}}.rotateOutUpLeft{animation-name:rotateOutUpLeft}@keyframes rotateOutUpRight{0%{transform-origin:right bottom;opacity:1}to{transform-origin:right bottom;transform:rotate(90deg);opacity:0}}.rotateOutUpRight{animation-name:rotateOutUpRight}@keyframes hinge{0%{transform-origin:top left;animation-timing-function:ease-in-out}20%,60%{transform:rotate(80deg);transform-origin:top left;animation-timing-function:ease-in-out}40%,80%{transform:rotate(60deg);transform-origin:top left;animation-timing-function:ease-in-out;opacity:1}to{transform:translate3d(0,700px,0);opacity:0}}.hinge{animation-name:hinge}@keyframes jackInTheBox{0%{opacity:0;transform:scale(.1) rotate(30deg);transform-origin:center bottom}50%{transform:rotate(-10deg)}70%{transform:rotate(3deg)}to{opacity:1;transform:scale(1)}}.jackInTheBox{animation-name:jackInTheBox}@keyframes rollIn{0%{opacity:0;transform:translate3d(-100%,0,0) rotate(-120deg)}to{opacity:1;transform:none}}.rollIn{animation-name:rollIn}@keyframes rollOut{0%{opacity:1}to{opacity:0;transform:translate3d(100%,0,0) rotate(120deg)}}.rollOut{animation-name:rollOut}@keyframes zoomIn{0%{opacity:0;transform:scale3d(.3,.3,.3)}50%{opacity:1}}.zoomIn{animation-name:zoomIn}@keyframes zoomInDown{0%{opacity:0;transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;transform:scale3d(.475,.475,.475) translate3d(0,60px,0);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomInDown{animation-name:zoomInDown}@keyframes zoomInLeft{0%{opacity:0;transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;transform:scale3d(.475,.475,.475) translate3d(10px,0,0);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomInLeft{animation-name:zoomInLeft}@keyframes zoomInRight{0%{opacity:0;transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomInRight{animation-name:zoomInRight}@keyframes zoomInUp{0%{opacity:0;transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomInUp{animation-name:zoomInUp}@keyframes zoomOut{0%{opacity:1}50%{opacity:0;transform:scale3d(.3,.3,.3)}to{opacity:0}}.zoomOut{animation-name:zoomOut}@keyframes zoomOutDown{40%{opacity:1;transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}to{opacity:0;transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);transform-origin:center bottom;animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomOutDown{animation-name:zoomOutDown}@keyframes zoomOutLeft{40%{opacity:1;transform:scale3d(.475,.475,.475) translate3d(42px,0,0)}to{opacity:0;transform:scale(.1) translate3d(-2000px,0,0);transform-origin:left center}}.zoomOutLeft{animation-name:zoomOutLeft}@keyframes zoomOutRight{40%{opacity:1;transform:scale3d(.475,.475,.475) translate3d(-42px,0,0)}to{opacity:0;transform:scale(.1) translate3d(2000px,0,0);transform-origin:right center}}.zoomOutRight{animation-name:zoomOutRight}@keyframes zoomOutUp{40%{opacity:1;transform:scale3d(.475,.475,.475) translate3d(0,60px,0);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}to{opacity:0;transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);transform-origin:center bottom;animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomOutUp{animation-name:zoomOutUp}@keyframes slideInDown{0%{transform:translate3d(0,-100%,0);visibility:visible}to{transform:translateZ(0)}}.slideInDown{animation-name:slideInDown}@keyframes slideInLeft{0%{transform:translate3d(-100%,0,0);visibility:visible}to{transform:translateZ(0)}}.slideInLeft{animation-name:slideInLeft}@keyframes slideInRight{0%{transform:translate3d(100%,0,0);visibility:visible}to{transform:translateZ(0)}}.slideInRight{animation-name:slideInRight}@keyframes slideInUp{0%{transform:translate3d(0,100%,0);visibility:visible}to{transform:translateZ(0)}}.slideInUp{animation-name:slideInUp}@keyframes slideOutDown{0%{transform:translateZ(0)}to{visibility:hidden;transform:translate3d(0,100%,0)}}.slideOutDown{animation-name:slideOutDown}@keyframes slideOutLeft{0%{transform:translateZ(0)}to{visibility:hidden;transform:translate3d(-100%,0,0)}}.slideOutLeft{animation-name:slideOutLeft}@keyframes slideOutRight{0%{transform:translateZ(0)}to{visibility:hidden;transform:translate3d(100%,0,0)}}.slideOutRight{animation-name:slideOutRight}@keyframes slideOutUp{0%{transform:translateZ(0)}to{visibility:hidden;transform:translate3d(0,-100%,0)}}.slideOutUp{animation-name:slideOutUp}
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>年会抽奖</title>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"
/>
<!-- <link rel="stylesheet" href="./index.css"> -->
</head>
<body>
<script src="./lib/three.min.js"></script>
<script src="./lib/tween.min.js"></script>
<script src="./lib/TrackballControls.js"></script>
<script src="./lib/CSS3DRenderer.js"></script>
<script src="./lib/ajax.js"></script>
<div class="canvas-box">
<canvas id="canvas">你的浏览器不支持canvas</canvas>
</div>
<div class="music">
<audio id="music" src="./data/music.mp3" class="music-item" loop></audio>
<div id="musicBox" class="music-box" title="播放/暂停背景音乐">Music</div>
</div>
<div id="prizeBar"></div>
<div id="container"></div>
<div id="powerby">InsCode 提供技术支持</div>
<div id="menu">
<button id="enter">进入抽奖</button>
<div id="lotteryBar" class="none">
<button id="lottery">开始抽奖</button>
<button id="reLottery">重新抽奖</button>
<div class="fixed-bar">
<button id="save" class="fixed-btn">导出抽奖结果</button>
<button id="reset" class="fixed-btn">重置</button>
<button id="fullScreen" class="fixed-btn">全屏</button>
</div>
</div>
</div>
<div class="qipao-container"></div>
</body>
</html>
/**
* Based on http://www.emagix.net/academic/mscs-project/item/camera-sync-with-css3-and-webgl-threejs
* @author mrdoob / http://mrdoob.com/
* @author yomotsu / https://yomotsu.net/
*/
THREE.CSS3DObject = function ( element ) {
THREE.Object3D.call( this );
this.element = element;
this.element.style.position = 'absolute';
this.addEventListener( 'removed', function () {
if ( this.element.parentNode !== null ) {
this.element.parentNode.removeChild( this.element );
}
} );
};
THREE.CSS3DObject.prototype = Object.create( THREE.Object3D.prototype );
THREE.CSS3DObject.prototype.constructor = THREE.CSS3DObject;
THREE.CSS3DSprite = function ( element ) {
THREE.CSS3DObject.call( this, element );
};
THREE.CSS3DSprite.prototype = Object.create( THREE.CSS3DObject.prototype );
THREE.CSS3DSprite.prototype.constructor = THREE.CSS3DSprite;
//
THREE.CSS3DRenderer = function () {
console.log( 'THREE.CSS3DRenderer', THREE.REVISION );
var _width, _height;
var _widthHalf, _heightHalf;
var matrix = new THREE.Matrix4();
var cache = {
camera: { fov: 0, style: '' },
objects: new WeakMap()
};
var domElement = document.createElement( 'div' );
domElement.style.overflow = 'hidden';
this.domElement = domElement;
var cameraElement = document.createElement( 'div' );
cameraElement.style.WebkitTransformStyle = 'preserve-3d';
cameraElement.style.transformStyle = 'preserve-3d';
domElement.appendChild( cameraElement );
var isIE = /Trident/i.test( navigator.userAgent );
this.getSize = function () {
return {
width: _width,
height: _height
};
};
this.setSize = function ( width, height ) {
_width = width;
_height = height;
_widthHalf = _width / 2;
_heightHalf = _height / 2;
domElement.style.width = width + 'px';
domElement.style.height = height + 'px';
cameraElement.style.width = width + 'px';
cameraElement.style.height = height + 'px';
};
function epsilon( value ) {
return Math.abs( value ) < 1e-10 ? 0 : value;
}
function getCameraCSSMatrix( matrix ) {
var elements = matrix.elements;
return 'matrix3d(' +
epsilon( elements[ 0 ] ) + ',' +
epsilon( - elements[ 1 ] ) + ',' +
epsilon( elements[ 2 ] ) + ',' +
epsilon( elements[ 3 ] ) + ',' +
epsilon( elements[ 4 ] ) + ',' +
epsilon( - elements[ 5 ] ) + ',' +
epsilon( elements[ 6 ] ) + ',' +
epsilon( elements[ 7 ] ) + ',' +
epsilon( elements[ 8 ] ) + ',' +
epsilon( - elements[ 9 ] ) + ',' +
epsilon( elements[ 10 ] ) + ',' +
epsilon( elements[ 11 ] ) + ',' +
epsilon( elements[ 12 ] ) + ',' +
epsilon( - elements[ 13 ] ) + ',' +
epsilon( elements[ 14 ] ) + ',' +
epsilon( elements[ 15 ] ) +
')';
}
function getObjectCSSMatrix( matrix, cameraCSSMatrix ) {
var elements = matrix.elements;
var matrix3d = 'matrix3d(' +
epsilon( elements[ 0 ] ) + ',' +
epsilon( elements[ 1 ] ) + ',' +
epsilon( elements[ 2 ] ) + ',' +
epsilon( elements[ 3 ] ) + ',' +
epsilon( - elements[ 4 ] ) + ',' +
epsilon( - elements[ 5 ] ) + ',' +
epsilon( - elements[ 6 ] ) + ',' +
epsilon( - elements[ 7 ] ) + ',' +
epsilon( elements[ 8 ] ) + ',' +
epsilon( elements[ 9 ] ) + ',' +
epsilon( elements[ 10 ] ) + ',' +
epsilon( elements[ 11 ] ) + ',' +
epsilon( elements[ 12 ] ) + ',' +
epsilon( elements[ 13 ] ) + ',' +
epsilon( elements[ 14 ] ) + ',' +
epsilon( elements[ 15 ] ) +
')';
if ( isIE ) {
return 'translate(-50%,-50%)' +
'translate(' + _widthHalf + 'px,' + _heightHalf + 'px)' +
cameraCSSMatrix +
matrix3d;
}
return 'translate(-50%,-50%)' + matrix3d;
}
function renderObject( object, camera, cameraCSSMatrix ) {
if ( object instanceof THREE.CSS3DObject ) {
var style;
if ( object instanceof THREE.CSS3DSprite ) {
// http://swiftcoder.wordpress.com/2008/11/25/constructing-a-billboard-matrix/
matrix.copy( camera.matrixWorldInverse );
matrix.transpose();
matrix.copyPosition( object.matrixWorld );
matrix.scale( object.scale );
matrix.elements[ 3 ] = 0;
matrix.elements[ 7 ] = 0;
matrix.elements[ 11 ] = 0;
matrix.elements[ 15 ] = 1;
style = getObjectCSSMatrix( matrix, cameraCSSMatrix );
} else {
style = getObjectCSSMatrix( object.matrixWorld, cameraCSSMatrix );
}
var element = object.element;
var cachedObject = cache.objects.get( object );
if ( cachedObject === undefined || cachedObject.style !== style ) {
element.style.WebkitTransform = style;
element.style.transform = style;
var objectData = { style: style };
if ( isIE ) {
objectData.distanceToCameraSquared = getDistanceToSquared( camera, object );
}
cache.objects.set( object, objectData );
}
if ( element.parentNode !== cameraElement ) {
cameraElement.appendChild( element );
}
}
for ( var i = 0, l = object.children.length; i < l; i ++ ) {
renderObject( object.children[ i ], camera, cameraCSSMatrix );
}
}
var getDistanceToSquared = function () {
var a = new THREE.Vector3();
var b = new THREE.Vector3();
return function ( object1, object2 ) {
a.setFromMatrixPosition( object1.matrixWorld );
b.setFromMatrixPosition( object2.matrixWorld );
return a.distanceToSquared( b );
};
}();
function filterAndFlatten( scene ) {
var result = [];
scene.traverse( function ( object ) {
if ( object instanceof THREE.CSS3DObject ) result.push( object );
} );
return result;
}
function zOrder( scene ) {
var sorted = filterAndFlatten( scene ).sort( function ( a, b ) {
var distanceA = cache.objects.get( a ).distanceToCameraSquared;
var distanceB = cache.objects.get( b ).distanceToCameraSquared;
return distanceA - distanceB;
} );
var zMax = sorted.length;
for ( var i = 0, l = sorted.length; i < l; i ++ ) {
sorted[ i ].element.style.zIndex = zMax - i;
}
}
this.render = function ( scene, camera ) {
var fov = camera.projectionMatrix.elements[ 5 ] * _heightHalf;
if ( cache.camera.fov !== fov ) {
if ( camera.isPerspectiveCamera ) {
domElement.style.WebkitPerspective = fov + 'px';
domElement.style.perspective = fov + 'px';
}
cache.camera.fov = fov;
}
scene.updateMatrixWorld();
if ( camera.parent === null ) camera.updateMatrixWorld();
if ( camera.isOrthographicCamera ) {
var tx = - ( camera.right + camera.left ) / 2;
var ty = ( camera.top + camera.bottom ) / 2;
}
var cameraCSSMatrix = camera.isOrthographicCamera ?
'scale(' + fov + ')' + 'translate(' + epsilon( tx ) + 'px,' + epsilon( ty ) + 'px)' + getCameraCSSMatrix( camera.matrixWorldInverse ) :
'translateZ(' + fov + 'px)' + getCameraCSSMatrix( camera.matrixWorldInverse );
var style = cameraCSSMatrix +
'translate(' + _widthHalf + 'px,' + _heightHalf + 'px)';
if ( cache.camera.style !== style && ! isIE ) {
cameraElement.style.WebkitTransform = style;
cameraElement.style.transform = style;
cache.camera.style = style;
}
renderObject( scene, camera, cameraCSSMatrix );
if ( isIE ) {
// IE10 and 11 does not support 'preserve-3d'.
// Thus, z-order in 3D will not work.
// We have to calc z-order manually and set CSS z-index for IE.
// FYI: z-index can't handle object intersection
zOrder( scene );
}
};
};
/**
* @author Eberhard Graether / http://egraether.com/
* @author Mark Lundin / http://mark-lundin.com
* @author Simone Manini / http://daron1337.github.io
* @author Luca Antiga / http://lantiga.github.io
*/
THREE.TrackballControls = function(object, domElement) {
var _this = this;
var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
this.object = object;
this.domElement = (domElement !== undefined) ? domElement : document;
// API
this.enabled = true;
this.screen = { left: 0, top: 0, width: 0, height: 0 };
this.rotateSpeed = 1.0;
this.zoomSpeed = 1.2;
this.panSpeed = 0.3;
this.noRotate = false;
this.noZoom = false;
this.noPan = false;
this.staticMoving = false;
this.dynamicDampingFactor = 0.2;
this.minDistance = 0;
this.maxDistance = Infinity;
this.keys = [65 /*A*/ , 83 /*S*/ , 68 /*D*/ ];
// internals
this.target = new THREE.Vector3();
var EPS = 0.000001;
var lastPosition = new THREE.Vector3();
var _state = STATE.NONE,
_prevState = STATE.NONE,
_eye = new THREE.Vector3(),
_movePrev = new THREE.Vector2(),
_moveCurr = new THREE.Vector2(),
_lastAxis = new THREE.Vector3(),
_lastAngle = 0,
_zoomStart = new THREE.Vector2(),
_zoomEnd = new THREE.Vector2(),
_touchZoomDistanceStart = 0,
_touchZoomDistanceEnd = 0,
_panStart = new THREE.Vector2(),
_panEnd = new THREE.Vector2();
// for reset
this.target0 = this.target.clone();
this.position0 = this.object.position.clone();
this.up0 = this.object.up.clone();
// events
var changeEvent = { type: 'change' };
var startEvent = { type: 'start' };
var endEvent = { type: 'end' };
// methods
this.handleResize = function() {
if (this.domElement === document) {
this.screen.left = 0;
this.screen.top = 0;
this.screen.width = window.innerWidth;
this.screen.height = window.innerHeight;
} else {
var box = this.domElement.getBoundingClientRect();
// adjustments come from similar code in the jquery offset() function
var d = this.domElement.ownerDocument.documentElement;
this.screen.left = box.left + window.pageXOffset - d.clientLeft;
this.screen.top = box.top + window.pageYOffset - d.clientTop;
this.screen.width = box.width;
this.screen.height = box.height;
}
};
var getMouseOnScreen = (function() {
var vector = new THREE.Vector2();
return function getMouseOnScreen(pageX, pageY) {
vector.set(
(pageX - _this.screen.left) / _this.screen.width,
(pageY - _this.screen.top) / _this.screen.height
);
return vector;
};
}());
var getMouseOnCircle = (function() {
var vector = new THREE.Vector2();
return function getMouseOnCircle(pageX, pageY) {
vector.set(
((pageX - _this.screen.width * 0.5 - _this.screen.left) / (_this.screen.width * 0.5)),
((_this.screen.height + 2 * (_this.screen.top - pageY)) / _this.screen.width) // screen.width intentional
);
return vector;
};
}());
this.rotateCamera = (function() {
var axis = new THREE.Vector3(),
quaternion = new THREE.Quaternion(),
eyeDirection = new THREE.Vector3(),
objectUpDirection = new THREE.Vector3(),
objectSidewaysDirection = new THREE.Vector3(),
moveDirection = new THREE.Vector3(),
angle;
return function rotateCamera() {
moveDirection.set(_moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0);
angle = moveDirection.length();
if (angle) {
_eye.copy(_this.object.position).sub(_this.target);
eyeDirection.copy(_eye).normalize();
objectUpDirection.copy(_this.object.up).normalize();
objectSidewaysDirection.crossVectors(objectUpDirection, eyeDirection).normalize();
objectUpDirection.setLength(_moveCurr.y - _movePrev.y);
objectSidewaysDirection.setLength(_moveCurr.x - _movePrev.x);
moveDirection.copy(objectUpDirection.add(objectSidewaysDirection));
axis.crossVectors(moveDirection, _eye).normalize();
angle *= _this.rotateSpeed;
quaternion.setFromAxisAngle(axis, angle);
_eye.applyQuaternion(quaternion);
_this.object.up.applyQuaternion(quaternion);
_lastAxis.copy(axis);
_lastAngle = angle;
} else if (!_this.staticMoving && _lastAngle) {
_lastAngle *= Math.sqrt(1.0 - _this.dynamicDampingFactor);
_eye.copy(_this.object.position).sub(_this.target);
quaternion.setFromAxisAngle(_lastAxis, _lastAngle);
_eye.applyQuaternion(quaternion);
_this.object.up.applyQuaternion(quaternion);
}
_movePrev.copy(_moveCurr);
};
}());
this.zoomCamera = function() {
var factor;
if (_state === STATE.TOUCH_ZOOM_PAN) {
factor = _touchZoomDistanceStart / _touchZoomDistanceEnd;
_touchZoomDistanceStart = _touchZoomDistanceEnd;
_eye.multiplyScalar(factor);
} else {
factor = 1.0 + (_zoomEnd.y - _zoomStart.y) * _this.zoomSpeed;
if (factor !== 1.0 && factor > 0.0) {
_eye.multiplyScalar(factor);
}
if (_this.staticMoving) {
_zoomStart.copy(_zoomEnd);
} else {
_zoomStart.y += (_zoomEnd.y - _zoomStart.y) * this.dynamicDampingFactor;
}
}
};
this.panCamera = (function() {
var mouseChange = new THREE.Vector2(),
objectUp = new THREE.Vector3(),
pan = new THREE.Vector3();
return function panCamera() {
mouseChange.copy(_panEnd).sub(_panStart);
if (mouseChange.lengthSq()) {
mouseChange.multiplyScalar(_eye.length() * _this.panSpeed);
pan.copy(_eye).cross(_this.object.up).setLength(mouseChange.x);
pan.add(objectUp.copy(_this.object.up).setLength(mouseChange.y));
_this.object.position.add(pan);
_this.target.add(pan);
if (_this.staticMoving) {
_panStart.copy(_panEnd);
} else {
_panStart.add(mouseChange.subVectors(_panEnd, _panStart).multiplyScalar(_this.dynamicDampingFactor));
}
}
};
}());
this.checkDistances = function() {
if (!_this.noZoom || !_this.noPan) {
if (_eye.lengthSq() > _this.maxDistance * _this.maxDistance) {
_this.object.position.addVectors(_this.target, _eye.setLength(_this.maxDistance));
_zoomStart.copy(_zoomEnd);
}
if (_eye.lengthSq() < _this.minDistance * _this.minDistance) {
_this.object.position.addVectors(_this.target, _eye.setLength(_this.minDistance));
_zoomStart.copy(_zoomEnd);
}
}
};
this.update = function() {
_eye.subVectors(_this.object.position, _this.target);
if (!_this.noRotate) {
_this.rotateCamera();
}
if (!_this.noZoom) {
_this.zoomCamera();
}
if (!_this.noPan) {
_this.panCamera();
}
_this.object.position.addVectors(_this.target, _eye);
_this.checkDistances();
_this.object.lookAt(_this.target);
if (lastPosition.distanceToSquared(_this.object.position) > EPS) {
_this.dispatchEvent(changeEvent);
lastPosition.copy(_this.object.position);
}
};
this.reset = function() {
_state = STATE.NONE;
_prevState = STATE.NONE;
_this.target.copy(_this.target0);
_this.object.position.copy(_this.position0);
_this.object.up.copy(_this.up0);
_eye.subVectors(_this.object.position, _this.target);
_this.object.lookAt(_this.target);
_this.dispatchEvent(changeEvent);
lastPosition.copy(_this.object.position);
};
// listeners
function keydown(event) {
if (_this.enabled === false) return;
window.removeEventListener('keydown', keydown);
_prevState = _state;
if (_state !== STATE.NONE) {
return;
} else if (event.keyCode === _this.keys[STATE.ROTATE] && !_this.noRotate) {
_state = STATE.ROTATE;
} else if (event.keyCode === _this.keys[STATE.ZOOM] && !_this.noZoom) {
_state = STATE.ZOOM;
} else if (event.keyCode === _this.keys[STATE.PAN] && !_this.noPan) {
_state = STATE.PAN;
}
}
function keyup(event) {
if (_this.enabled === false) return;
_state = _prevState;
window.addEventListener('keydown', keydown, false);
}
function mousedown(event) {
if (_this.enabled === false) return;
event.preventDefault();
event.stopPropagation();
if (_state === STATE.NONE) {
_state = event.button;
}
// 阻止浏览器的默认行为
return;
if (_state === STATE.ROTATE && !_this.noRotate) {
_moveCurr.copy(getMouseOnCircle(event.pageX, event.pageY));
_movePrev.copy(_moveCurr);
} else if (_state === STATE.ZOOM && !_this.noZoom) {
_zoomStart.copy(getMouseOnScreen(event.pageX, event.pageY));
_zoomEnd.copy(_zoomStart);
} else if (_state === STATE.PAN && !_this.noPan) {
_panStart.copy(getMouseOnScreen(event.pageX, event.pageY));
_panEnd.copy(_panStart);
}
document.addEventListener('mousemove', mousemove, false);
document.addEventListener('mouseup', mouseup, false);
_this.dispatchEvent(startEvent);
}
function mousemove(event) {
if (_this.enabled === false) return;
event.preventDefault();
event.stopPropagation();
if (_state === STATE.ROTATE && !_this.noRotate) {
_movePrev.copy(_moveCurr);
_moveCurr.copy(getMouseOnCircle(event.pageX, event.pageY));
} else if (_state === STATE.ZOOM && !_this.noZoom) {
_zoomEnd.copy(getMouseOnScreen(event.pageX, event.pageY));
} else if (_state === STATE.PAN && !_this.noPan) {
_panEnd.copy(getMouseOnScreen(event.pageX, event.pageY));
}
}
function mouseup(event) {
if (_this.enabled === false) return;
event.preventDefault();
event.stopPropagation();
_state = STATE.NONE;
document.removeEventListener('mousemove', mousemove);
document.removeEventListener('mouseup', mouseup);
_this.dispatchEvent(endEvent);
}
function mousewheel(event) {
if (_this.enabled === false) return;
if (_this.noZoom === true) return;
event.preventDefault();
event.stopPropagation();
return;
switch (event.deltaMode) {
case 2:
// Zoom in pages
_zoomStart.y -= event.deltaY * 0.025;
break;
case 1:
// Zoom in lines
_zoomStart.y -= event.deltaY * 0.01;
break;
default:
// undefined, 0, assume pixels
_zoomStart.y -= event.deltaY * 0.00025;
break;
}
_this.dispatchEvent(startEvent);
_this.dispatchEvent(endEvent);
}
function touchstart(event) {
if (_this.enabled === false) return;
event.preventDefault();
switch (event.touches.length) {
case 1:
_state = STATE.TOUCH_ROTATE;
_moveCurr.copy(getMouseOnCircle(event.touches[0].pageX, event.touches[0].pageY));
_movePrev.copy(_moveCurr);
break;
default: // 2 or more
_state = STATE.TOUCH_ZOOM_PAN;
var dx = event.touches[0].pageX - event.touches[1].pageX;
var dy = event.touches[0].pageY - event.touches[1].pageY;
_touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt(dx * dx + dy * dy);
var x = (event.touches[0].pageX + event.touches[1].pageX) / 2;
var y = (event.touches[0].pageY + event.touches[1].pageY) / 2;
_panStart.copy(getMouseOnScreen(x, y));
_panEnd.copy(_panStart);
break;
}
_this.dispatchEvent(startEvent);
}
function touchmove(event) {
if (_this.enabled === false) return;
event.preventDefault();
event.stopPropagation();
switch (event.touches.length) {
case 1:
_movePrev.copy(_moveCurr);
_moveCurr.copy(getMouseOnCircle(event.touches[0].pageX, event.touches[0].pageY));
break;
default: // 2 or more
var dx = event.touches[0].pageX - event.touches[1].pageX;
var dy = event.touches[0].pageY - event.touches[1].pageY;
_touchZoomDistanceEnd = Math.sqrt(dx * dx + dy * dy);
var x = (event.touches[0].pageX + event.touches[1].pageX) / 2;
var y = (event.touches[0].pageY + event.touches[1].pageY) / 2;
_panEnd.copy(getMouseOnScreen(x, y));
break;
}
}
function touchend(event) {
if (_this.enabled === false) return;
switch (event.touches.length) {
case 0:
_state = STATE.NONE;
break;
case 1:
_state = STATE.TOUCH_ROTATE;
_moveCurr.copy(getMouseOnCircle(event.touches[0].pageX, event.touches[0].pageY));
_movePrev.copy(_moveCurr);
break;
}
_this.dispatchEvent(endEvent);
}
function contextmenu(event) {
if (_this.enabled === false) return;
event.preventDefault();
}
this.dispose = function() {
this.domElement.removeEventListener('contextmenu', contextmenu, false);
this.domElement.removeEventListener('mousedown', mousedown, false);
this.domElement.removeEventListener('wheel', mousewheel, false);
this.domElement.removeEventListener('touchstart', touchstart, false);
this.domElement.removeEventListener('touchend', touchend, false);
this.domElement.removeEventListener('touchmove', touchmove, false);
document.removeEventListener('mousemove', mousemove, false);
document.removeEventListener('mouseup', mouseup, false);
window.removeEventListener('keydown', keydown, false);
window.removeEventListener('keyup', keyup, false);
};
this.domElement.addEventListener('contextmenu', contextmenu, false);
this.domElement.addEventListener('mousedown', mousedown, false);
this.domElement.addEventListener('wheel', mousewheel, false);
this.domElement.addEventListener('touchstart', touchstart, false);
this.domElement.addEventListener('touchend', touchend, false);
this.domElement.addEventListener('touchmove', touchmove, false);
window.addEventListener('keydown', keydown, false);
window.addEventListener('keyup', keyup, false);
this.handleResize();
// force an update at start
this.update();
};
THREE.TrackballControls.prototype = Object.create(THREE.EventDispatcher.prototype);
THREE.TrackballControls.prototype.constructor = THREE.TrackballControls;
\ No newline at end of file
window.AJAX = function (opt) {
opt = Object.assign({}, {
type: 'POST',
async: true,
isJson: true
}, opt || {});
let xhr, data;
if (window.XMLHttpRequest) { // Mozilla, Safari, IE7+ ...
xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE 6 and older
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
if (opt.isJson) {
data = JSON.stringify(opt.data);
}
xhr.onreadystatechange = function () {
// try {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
let res = xhr.responseText;
opt.isJson && (res = JSON.parse(res));
opt.success && opt.success(res);
} else {
console.log('There was a problem with the request.');
}
}
// } catch (e) {
// console.error('Caught Exception: ' + e);
// }
}
xhr.open(opt.type, opt.url, opt.async);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(data);
}
\ No newline at end of file
此差异已折叠。
"use strict";var TWEEN=TWEEN||(function(){var b=[];return{REVISION:"7",getAll:function(){return b},removeAll:function(){b=[]},add:function(a){b.push(a)},remove:function(a){a=b.indexOf(a);-1!==a&&b.splice(a,1)},update:function(f){if(0===b.length){return !1}for(var a=0,e=b.length,f=void 0!==f?f:Date.now();a<e;){b[a].update(f)?a++:(b.splice(a,1),e--)}return !0}}})();TWEEN.Tween=function(A){var y={},z={},x=1000,w=0,v=null,u=TWEEN.Easing.Linear.None,g=TWEEN.Interpolation.Linear,t=[],q=null,o=!1,j=null,B=null,i=null;this.to=function(b,d){null!==d&&(x=d);z=b;return this};this.start=function(b){TWEEN.add(this);o=!1;v=void 0!==b?b:Date.now();v+=w;for(var a in z){if(null!==A[a]){if(z[a] instanceof Array){if(0===z[a].length){continue}z[a]=[A[a]].concat(z[a])}y[a]=A[a]}}return this};this.stop=function(){TWEEN.remove(this);B&&B.call(this);return this};this.delay=function(b){w=b;return this};this.easing=function(b){u=b;return this};this.interpolation=function(b){g=b;return this};this.chain=function(){t=arguments;return this};this.onStart=function(b){q=b;return this};this.onStop=function(b){B=b;return this};this.onUpdate=function(b){j=b;return this};this.onComplete=function(b){i=b;return this};this.update=function(h){if(h<v){return !0}!1===o&&(null!==q&&q.call(A),(o=!0));var d=(h-v)/x,d=1<d?1:d,b=u(d),a;for(a in y){var c=y[a],f=z[a];A[a]=f instanceof Array?g(f,b):c+(f-c)*b}null!==j&&j.call(A,b);if(1==d){null!==i&&i.call(A);d=0;for(b=t.length;d<b;d++){t[d].start(h)}return !1}return !0}};TWEEN.Easing={Linear:{None:function(b){return b}},Quadratic:{In:function(b){return b*b},Out:function(b){return b*(2-b)},InOut:function(b){return 1>(b*=2)?0.5*b*b:-0.5*(--b*(b-2)-1)}},Cubic:{In:function(b){return b*b*b},Out:function(b){return --b*b*b+1},InOut:function(b){return 1>(b*=2)?0.5*b*b*b:0.5*((b-=2)*b*b+2)}},Quartic:{In:function(b){return b*b*b*b},Out:function(b){return 1- --b*b*b*b},InOut:function(b){return 1>(b*=2)?0.5*b*b*b*b:-0.5*((b-=2)*b*b*b-2)}},Quintic:{In:function(b){return b*b*b*b*b},Out:function(b){return --b*b*b*b*b+1},InOut:function(b){return 1>(b*=2)?0.5*b*b*b*b*b:0.5*((b-=2)*b*b*b*b+2)}},Sinusoidal:{In:function(b){return 1-Math.cos((b*Math.PI)/2)},Out:function(b){return Math.sin((b*Math.PI)/2)},InOut:function(b){return 0.5*(1-Math.cos(Math.PI*b))}},Exponential:{In:function(b){return 0===b?0:Math.pow(1024,b-1)},Out:function(b){return 1===b?1:1-Math.pow(2,-10*b)},InOut:function(b){return 0===b?0:1===b?1:1>(b*=2)?0.5*Math.pow(1024,b-1):0.5*(-Math.pow(2,-10*(b-1))+2)}},Circular:{In:function(b){return 1-Math.sqrt(1-b*b)},Out:function(b){return Math.sqrt(1- --b*b)},InOut:function(b){return 1>(b*=2)?-0.5*(Math.sqrt(1-b*b)-1):0.5*(Math.sqrt(1-(b-=2)*b)+1)}},Elastic:{In:function(e){var f,d=0.1;if(0===e){return 0}if(1===e){return 1}!d||1>d?((d=1),(f=0.1)):(f=(0.4*Math.asin(1/d))/(2*Math.PI));return -(d*Math.pow(2,10*(e-=1))*Math.sin(((e-f)*2*Math.PI)/0.4))},Out:function(e){var f,d=0.1;if(0===e){return 0}if(1===e){return 1}!d||1>d?((d=1),(f=0.1)):(f=(0.4*Math.asin(1/d))/(2*Math.PI));return(d*Math.pow(2,-10*e)*Math.sin(((e-f)*2*Math.PI)/0.4)+1)},InOut:function(e){var f,d=0.1;if(0===e){return 0}if(1===e){return 1}!d||1>d?((d=1),(f=0.1)):(f=(0.4*Math.asin(1/d))/(2*Math.PI));return 1>(e*=2)?-0.5*d*Math.pow(2,10*(e-=1))*Math.sin(((e-f)*2*Math.PI)/0.4):0.5*d*Math.pow(2,-10*(e-=1))*Math.sin(((e-f)*2*Math.PI)/0.4)+1}},Back:{In:function(b){return b*b*(2.70158*b-1.70158)},Out:function(b){return --b*b*(2.70158*b+1.70158)+1},InOut:function(b){return 1>(b*=2)?0.5*b*b*(3.5949095*b-2.5949095):0.5*((b-=2)*b*(3.5949095*b+2.5949095)+2)}},Bounce:{In:function(b){return 1-TWEEN.Easing.Bounce.Out(1-b)},Out:function(b){return b<1/2.75?7.5625*b*b:b<2/2.75?7.5625*(b-=1.5/2.75)*b+0.75:b<2.5/2.75?7.5625*(b-=2.25/2.75)*b+0.9375:7.5625*(b-=2.625/2.75)*b+0.984375},InOut:function(b){return 0.5>b?0.5*TWEEN.Easing.Bounce.In(2*b):0.5*TWEEN.Easing.Bounce.Out(2*b-1)+0.5}}};TWEEN.Interpolation={Linear:function(h,l){var g=h.length-1,k=g*l,j=Math.floor(k),i=TWEEN.Interpolation.Utils.Linear;return 0>l?i(h[0],h[1],k):1<l?i(h[g],h[g-1],g-k):i(h[j],h[j+1>g?g:j+1],k-j)},Bezier:function(i,n){var g=0,m=i.length-1,l=Math.pow,k=TWEEN.Interpolation.Utils.Bernstein,j;for(j=0;j<=m;j++){g+=l(1-n,m-j)*l(n,j)*i[j]*k(m,j)}return g},CatmullRom:function(h,l){var g=h.length-1,k=g*l,j=Math.floor(k),i=TWEEN.Interpolation.Utils.CatmullRom;return h[0]===h[g]?(0>l&&(j=Math.floor((k=g*(1+l)))),i(h[(j-1+g)%g],h[j],h[(j+1)%g],h[(j+2)%g],k-j)):0>l?h[0]-(i(h[0],h[0],h[1],h[1],-k)-h[0]):1<l?h[g]-(i(h[g],h[g],h[g-1],h[g-1],k-g)-h[g]):i(h[j?j-1:0],h[j],h[g<j+1?g:j+1],h[g<j+2?g:j+2],k-j)},Utils:{Linear:function(e,f,d){return(f-e)*d+e},Bernstein:function(e,f){var d=TWEEN.Interpolation.Utils.Factorial;return d(e)/d(f)/d(e-f)},Factorial:(function(){var b=[1];return function(f){var a=1,e;if(b[f]){return b[f]}for(e=f;1<e;e--){a*=e}return(b[f]=a)}})(),CatmullRom:function(h,l,g,k,j){var h=0.5*(g-h),k=0.5*(k-l),i=j*j;return((2*l-2*g+h+k)*j*i+(-3*l+3*g-2*h-k)*i+h*j+l)}}};
\ No newline at end of file
(function () {
//based on an Example by @curran
window.requestAnimFrame = (function () {
return window.requestAnimationFrame;
})();
var canvas = document.getElementById("canvas");
~~(function setSize() {
//定义canvas的宽高,让他跟浏览器的窗口的宽高相同
window.onresize = arguments.callee;
w = window.innerWidth;
h = window.innerHeight;
canvas.width = w;
canvas.height = h;
})();
var c = canvas.getContext("2d");
var numStars = 800;
var radius = "0." + Math.floor(Math.random() * 9) + 1;
var focalLength = canvas.width * 2;
var warp = 0;
var centerX, centerY;
var stars = [],
star;
var i;
var animate = true;
initializeStars();
function executeFrame() {
if (animate) requestAnimFrame(executeFrame);
moveStars();
drawStars();
}
function initializeStars() {
centerX = canvas.width / 2;
centerY = canvas.height / 2;
stars = [];
for (i = 0; i < numStars; i++) {
star = {
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
z: Math.random() * canvas.width,
o: "0." + Math.floor(Math.random() * 99) + 1
};
stars.push(star);
}
}
function moveStars() {
for (i = 0; i < numStars; i++) {
star = stars[i];
star.z--;
if (star.z <= 0) {
star.z = canvas.width;
}
}
}
function drawStars() {
var pixelX, pixelY, pixelRadius;
// Resize to the screen
if (
canvas.width != window.innerWidth ||
canvas.width != window.innerWidth
) {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
initializeStars();
}
if (warp == 0) {
c.fillStyle = "rgba(0,10,20,1)";
c.fillRect(0, 0, canvas.width, canvas.height);
}
c.fillStyle = "rgba(209, 255, 255, " + radius + ")";
for (i = 0; i < numStars; i++) {
star = stars[i];
pixelX = (star.x - centerX) * (focalLength / star.z);
pixelX += centerX;
pixelY = (star.y - centerY) * (focalLength / star.z);
pixelY += centerY;
pixelRadius = 1 * (focalLength / star.z);
c.fillRect(pixelX, pixelY, pixelRadius, pixelRadius);
c.fillStyle = "rgba(209, 255, 255, " + star.o + ")";
//c.fill();
}
}
// document.getElementById('warp').addEventListener("click", function(e) {
// window.c.beginPath();
// window.c.clearRect(0, 0, window.canvas.width, window.canvas.height);
// window.warp = warp ? 0 : 1;
// executeFrame();
// });
executeFrame();
})();
const NUMBER_MATRIX = [
[
// 0
[0, 0],
[1, 0],
[2, 0],
[0, 1],
[2, 1],
[0, 2],
[2, 2],
[0, 3],
[2, 3],
[0, 4],
[1, 4],
[2, 4]
],
[
// 1
[1, 0],
[0, 1],
[1, 1],
[1, 2],
[1, 3],
[0, 4],
[1, 4],
[2, 4]
],
[
// 2
[0, 0],
[1, 0],
[2, 0],
[2, 1],
[0, 2],
[1, 2],
[2, 2],
[0, 3],
[0, 4],
[1, 4],
[2, 4]
],
[
// 3
[0, 0],
[1, 0],
[2, 0],
[2, 1],
[0, 2],
[1, 2],
[2, 2],
[2, 3],
[0, 4],
[1, 4],
[2, 4]
],
[
// 4
[0, 0],
[2, 0],
[0, 1],
[2, 1],
[0, 2],
[1, 2],
[2, 2],
[2, 3],
[2, 4]
],
[
// 5
[0, 0],
[1, 0],
[2, 0],
[0, 1],
[0, 2],
[1, 2],
[2, 2],
[2, 3],
[0, 4],
[1, 4],
[2, 4]
],
[
// 6
[0, 0],
[1, 0],
[2, 0],
[0, 1],
[0, 2],
[1, 2],
[2, 2],
[0, 3],
[2, 3],
[0, 4],
[1, 4],
[2, 4]
],
[
// 7
[0, 0],
[1, 0],
[2, 0],
[2, 1],
[2, 2],
[2, 3],
[2, 4]
],
[
// 8
[0, 0],
[1, 0],
[2, 0],
[0, 1],
[2, 1],
[0, 2],
[1, 2],
[2, 2],
[0, 3],
[2, 3],
[0, 4],
[1, 4],
[2, 4]
],
[
// 9
[0, 0],
[1, 0],
[2, 0],
[0, 1],
[2, 1],
[0, 2],
[1, 2],
[2, 2],
[2, 3],
[0, 4],
[1, 4],
[2, 4]
]
];
module.exports = {
NUMBER_MATRIX
};
html,
body {
height: 100%;
}
body {
background: linear-gradient(to bottom, #131313 0%, #02101c 100%);
margin: 0;
font-family: Helvetica, sans-serif;
overflow: hidden;
}
a {
color: #ffffff;
}
.none {
display: none;
}
#container {
z-index: 3;
position: relative;
margin: 0 15vh;
}
#menu {
z-index: 4;
margin-left: 15vh;
}
#powerby {
z-index: 4;
position: absolute;
left:0vh;
bottom: 0vh;
text-align: left;
font-size: 32px;
font-weight: bold;
color: #fff;
padding: 2vh;
font-size: 3vh;
line-height: 3vh;
}
.canvas-box {
position: fixed;
left: 0;
top: 0;
z-index: -1;
}
#info {
position: absolute;
width: 100%;
color: #ffffff;
padding: 5px;
font-family: Monospace;
font-size: 13px;
font-weight: bold;
text-align: center;
z-index: 1;
}
#menu {
position: absolute;
bottom: 2vh;
width: 100%;
text-align: center;
}
.element {
width: 12vh;
height: 16vh;
box-shadow: 0 0 12px rgba(0, 255, 255, 0.5);
border: 1px solid rgba(127, 255, 255, 0.25);
text-align: center;
cursor: default;
transition: background-color 0.3s ease-in;
}
.element:hover {
box-shadow: 0 0 12px rgba(0, 255, 255, 0.75);
border: 1px solid rgba(127, 255, 255, 0.75);
}
.element .company {
position: absolute;
top: 1.2vh;
right: 0;
width: 100%;
font-size: 2vh;
color: rgba(127, 255, 255, 0.75);
}
.element .name {
position: absolute;
top: 4.6vh;
left: 0;
right: 0;
font-size: 2.9vh;
font-weight: bold;
color: rgba(255, 255, 255, 0.75);
text-shadow: 0 0 1vh rgba(0, 255, 255, 0.95);
}
.element .details {
position: absolute;
bottom: 1.2vh;
left: 0;
right: 0;
font-size: 1.6vh;
color: rgba(127, 255, 255, 0.75);
}
button {
color: rgba(127, 255, 255, 0.75);
background: transparent;
outline: 1px solid rgba(127, 255, 255, 0.75);
border: 0;
padding: 1.6vh 4vh;
margin: 0 4.6vh;
font-size: 2vh;
font-weight: bold;
cursor: pointer;
}
button:hover {
background-color: rgba(0, 255, 255, 0.5);
}
button:active {
color: #000000;
background-color: rgba(0, 255, 255, 0.75);
}
.highlight {
background-color: rgba(253, 105, 0, 0.95) !important;
box-shadow: 0 0 12px rgba(253, 105, 0, 0.95);
border: 1px solid rgba(253, 105, 0, 0.25);
}
.highlight.element .name {
text-shadow: 0 0 16px rgba(255, 255, 255, 0.95);
}
.prize.element .name {
text-shadow: none;
}
.prize.element {
transition: background-color 1.5s ease-in 0.3s;
background-color: rgba(253, 105, 0, 0.85) !important;
box-shadow: 0 0 12px rgba(253, 105, 0, 0.95);
}
.prize .company,
.prize .details,
.prize .name,
.highlight .company,
.highlight .name,
.highlight .details {
color: rgba(255, 255, 255, 0.85);
}
.dan-mu {
visibility: hidden;
position: fixed;
z-index: -1;
font-size: 12px;
top: 1vh;
left: 0;
padding: 0 1.2vh;
height: 2.2vh;
line-height: 2.2vh;
border-radius: 1vh;
box-sizing: border-box;
background-color: rgba(0, 127, 127, 0.37);
box-shadow: 0 0 4px rgba(0, 255, 255, 0.5);
border: 1px solid rgba(127, 255, 255, 0.25);
color: rgba(127, 255, 255, 0.75);
}
.dan-mu.active {
visibility: visible;
}
#prizeBar {
position: fixed;
left: 0;
padding-left: 1.2vh;
top: 1.2vh;
z-index: 2;
}
.prize-list {
margin: 0;
padding: 0;
list-style: none;
}
.prize-item {
padding: 9px;
margin: 6px 0;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
flex-wrap: nowrap;
background-color: rgba(0, 127, 127, 0.37);
border: 1px solid rgba(127, 255, 255, 0.25);
color: rgba(127, 255, 255, 0.75);
width: 30vh;
height: 10vh;
box-sizing: border-box;
transition: transform 1s ease-in;
}
.prize-item .prize-img {
width: 8vh;
height: 8vh;
margin-right: 1.2vh;
border-radius: 50%;
background-color: #fff;
text-shadow: 0 0 1vh rgba(0, 255, 255, 0.95);
overflow: hidden;
}
.prize-img img {
width: 90%;
height: 90%;
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.prize-text {
flex: 1;
}
.prize-title {
margin: 4px 0;
font-size: 1.8vh;
}
.prize-count {
padding: 4px 0;
position: relative;
}
.prize-count .progress {
height: 1.8vh;
background: rgba(0, 0, 0, 0.5);
padding: 1px;
overflow: visible;
border-radius: 1vh;
}
.progress .progress-bar {
border-radius: 1.8vh;
position: relative;
animation: animate-positive 2s;
background-color: #d9534f;
height: 1.8vh;
-webkit-transition: width 0.6s ease;
-o-transition: width 0.6s ease;
transition: width 0.6s ease;
}
.progress-bar.active {
animation: reverse progress-bar-stripes 0.4s linear infinite,
animate-positive 2s;
}
.progress-bar-striped {
background-image: -webkit-linear-gradient(45deg,
rgba(255, 255, 255, 0.15) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.15) 50%,
rgba(255, 255, 255, 0.15) 75%,
transparent 75%,
transparent);
background-image: -o-linear-gradient(45deg,
rgba(255, 255, 255, 0.15) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.15) 50%,
rgba(255, 255, 255, 0.15) 75%,
transparent 75%,
transparent);
background-image: linear-gradient(45deg,
rgba(255, 255, 255, 0.15) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.15) 50%,
rgba(255, 255, 255, 0.15) 75%,
transparent 75%,
transparent);
-webkit-background-size: 8px 8px;
background-size: 8px 8px;
}
@-webkit-keyframes animate-positive {
0% {
width: 0;
}
}
@keyframes animate-positive {
0% {
width: 0;
}
}
@-webkit-keyframes progress-bar-stripes {
from {
background-position: 8px 0;
}
to {
background-position: 0 0;
}
}
@-o-keyframes progress-bar-stripes {
from {
background-position: 8px 0;
}
to {
background-position: 0 0;
}
}
@keyframes progress-bar-stripes {
from {
background-position: 8px 0;
}
to {
background-position: 0 0;
}
}
.prize-count-left {
position: absolute;
color: #fff;
right: 9px;
font-size: 1.8vh;
line-height: 1.6vh;
top: 50%;
transform: translateY(-50%);
}
.shine {
box-shadow: 0 0 15px 0 rgba(0, 255, 255, 0.5);
transform: scale(1.2);
transform-origin: left center;
position: relative;
overflow: hidden;
}
.done {
position: relative;
}
.done:after {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
cursor: not-allowed;
}
.shine span {
position: absolute;
display: block
}
.shine span:nth-child(1) {
top: 0;
left: 0;
width: 100%;
height: 2px;
background: linear-gradient(90deg, transparent, #03e9f4);
animation: animate1 1s linear infinite
}
@keyframes animate1 {
0% {
left: -100%
}
50%,
100% {
left: 100%
}
}
.shine span:nth-child(2) {
top: -100%;
right: 0;
width: 2px;
height: 100%;
background: linear-gradient(180deg, transparent, #03e9f4);
animation: animate2 1s linear infinite;
animation-delay: .25s
}
@keyframes animate2 {
0% {
top: -100%
}
50%,
100% {
top: 100%
}
}
.shine span:nth-child(3) {
bottom: 0;
right: 0;
width: 100%;
height: 2px;
background: linear-gradient(270deg, transparent, #03e9f4);
animation: animate3 1s linear infinite;
animation-delay: .50s
}
@keyframes animate3 {
0% {
right: -100%
}
50%,
100% {
right: 100%
}
}
.shine span:nth-child(4) {
bottom: -100%;
left: 0;
width: 2px;
height: 100%;
background: linear-gradient(360deg, transparent, #03e9f4);
animation: animate4 1s linear infinite;
animation-delay: .75s
}
@keyframes animate4 {
0% {
bottom: -100%
}
50%,
100% {
bottom: 100%
}
}
.shine.prize-item {
/* width: 24vh; */
margin: 1.8vh 0;
}
.prize-mess {
color: #fff;
line-height: 5vh;
font-size: 1.6vh;
margin: 2.4vh 0;
}
.prize-shine {
font-size: 5vh;
font-weight: bold;
color: #db5c58;
vertical-align: middle;
padding: 0 6px;
}
.qipao-container {
position: fixed;
right: 0;
top: 10vh;
bottom: 1vh;
width: 24vh;
z-index: 2;
}
.qipao {
width: 100%;
padding: 1.8vh 1.4vh;
line-height: 1.414;
margin: 4px 0;
box-sizing: border-box;
font-size: 14px;
background-color: rgba(127, 255, 255, 0.25);
color: rgba(127, 255, 255, 0.75);
}
.music {
position: fixed;
top: 3vh;
right: 4vh;
z-index: 5;
}
.music-item {
display: block !important;
opacity: 0;
}
.music-box {
width: 5vh;
height: 5vh;
border-radius: 50%;
text-align: center;
line-height: 5vh;
font-size: 1.4vh;
color: #fff;
cursor: pointer;
background-color: rgba(253, 105, 0, 0.9);
border: 1px solid rgba(255, 255, 255, 0.5);
}
.rotate-active {
animation: rotate 4s linear infinite;
}
@keyframes rotate {
from {
transform: rotate(0);
}
to {
transform: rotate(360deg);
}
}
.margin-l-40 {
margin-left: 40px;
}
.fixed-bar {
position: fixed;
bottom: 20px;
right: 20px;
}
.fixed-btn {
margin: 20px 0 0;
width: 200px;
text-align: center;
display: block;
}
#lottery {
animation: breath 1.6s linear infinite;
box-shadow: 0px 0px 15px rgb(127 255 255 / 75%);
}
@keyframes breath {
0% {
transform: scale(0.9);
opacity: 0.8;
}
50% {
transform: scale(1.1);
opacity: 1;
}
100% {
transform: scale(0.9);
opacity: 0.8;
}
}
\ No newline at end of file
此差异已折叠。
const MAX_TOP = 300,
MAX_WIDTH = document.body.clientWidth;
let defaultType = 0;
let prizes;
const DEFAULT_MESS = [
"我是该抽中一等奖还是一等奖呢,纠结ing...",
"听说要提前一个月吃素才能中大奖喔!",
"好想要一等奖啊!!!",
"一等奖有没有人想要呢?",
"五等奖也不错,只要自己能中奖就行",
"祝大家新年快乐!",
"中不中奖不重要,大家吃好喝好。",
"新年,祝福大家事事顺遂。",
"作为专业陪跑的我,我就看看你们有谁跟我一样",
"新的一年祝福大家越来越好!",
"来年再战!!!"
];
let lastDanMuList = [];
let prizeElement = {},
lasetPrizeIndex = 0;
class DanMu {
constructor(option) {
if (typeof option !== "object") {
option = {
text: option
};
}
this.position = {};
this.text = option.text;
this.onComplete = option.onComplete;
this.init();
}
init() {
this.element = document.createElement("div");
this.element.className = "dan-mu";
document.body.appendChild(this.element);
this.start();
}
setText(text) {
this.text = text || this.text;
this.element.textContent = this.text;
this.width = this.element.clientWidth + 100;
}
start(text) {
let speed = ~~(Math.random() * 10000) + 6000;
this.position = {
x: MAX_WIDTH
};
let delay = speed / 10;
this.setText(text);
this.element.style.transform = "translateX(" + this.position.x + "px)";
this.element.style.top = ~~(Math.random() * MAX_TOP) + 10 + "px";
this.element.classList.add("active");
this.tween = new TWEEN.Tween(this.position)
.to(
{
x: -this.width
},
speed
)
.onUpdate(() => {
this.render();
})
.onComplete(() => {
this.onComplete && this.onComplete();
})
.start();
}
render() {
this.element.style.transform = "translateX(" + this.position.x + "px)";
}
}
class Qipao {
constructor(option) {
if (typeof option !== "object") {
option = {
text: option
};
}
this.text = option.text;
this.onComplete = option.onComplete;
this.$par = document.querySelector(".qipao-container");
if (!this.$par) {
this.$par = document.createElement("div");
this.$par.className = "qipao-container";
document.body.appendChild(this.$par);
}
this.init();
}
init() {
this.element = document.createElement("div");
this.element.className = "qipao animated";
this.$par.appendChild(this.element);
this.start();
}
setText(text) {
this.text = text || this.text;
this.element.textContent = this.text;
}
start(text) {
this.setText(text);
this.element.classList.remove("bounceOutRight");
this.element.classList.add("bounceInRight");
setTimeout(() => {
this.element.classList.remove("bounceInRight");
this.element.classList.add("bounceOutRight");
this.onComplete && this.onComplete();
}, 4000);
}
}
let addQipao = (() => {
let qipaoList = [];
return function (text) {
let qipao;
if (qipaoList.length > 0) {
qipao = qipaoList.shift();
} else {
qipao = new Qipao({
onComplete() {
qipaoList.push(qipao);
}
});
}
qipao.start(text);
};
})();
function setPrizes(pri) {
prizes = pri;
defaultType = prizes[0]["type"];
lasetPrizeIndex = pri.length - 1;
}
function showPrizeList(currentPrizeIndex) {
let currentPrize = prizes[currentPrizeIndex];
if (currentPrize.type === defaultType) {
currentPrize.count === "不限制";
}
let htmlCode = `<div class="prize-mess">正在抽取<label id="prizeType" class="prize-shine">${currentPrize.text}</label><label id="prizeText" class="prize-shine">${currentPrize.title}</label>,剩余<label id="prizeLeft" class="prize-shine">${currentPrize.count}</label>个</div><ul class="prize-list">`;
prizes.forEach(item => {
if (item.type === defaultType) {
return true;
}
htmlCode += `<li id="prize-item-${item.type}" class="prize-item ${
item.type == currentPrize.type ? "shine" : ""
}">
<span></span><span></span><span></span><span></span>
<div class="prize-img">
<img src="${item.img}" alt="${item.title}">
</div>
<div class="prize-text">
<h5 class="prize-title">${item.text} ${
item.title
}</h5>
<div class="prize-count">
<div class="progress">
<div id="prize-bar-${
item.type
}" class="progress-bar progress-bar-danger progress-bar-striped active" style="width: 100%;">
</div>
</div>
<div id="prize-count-${
item.type
}" class="prize-count-left">
${item.count + "/" + item.count}
</div>
</div>
</div>
</li>`;
});
htmlCode += `</ul>`;
document.querySelector("#prizeBar").innerHTML = htmlCode;
}
function resetPrize(currentPrizeIndex) {
prizeElement = {};
lasetPrizeIndex = currentPrizeIndex;
showPrizeList(currentPrizeIndex);
}
let setPrizeData = (function () {
return function (currentPrizeIndex, count, isInit) {
let currentPrize = prizes[currentPrizeIndex],
type = currentPrize.type,
elements = prizeElement[type],
totalCount = currentPrize.count;
if (!elements) {
elements = {
box: document.querySelector(`#prize-item-${type}`),
bar: document.querySelector(`#prize-bar-${type}`),
text: document.querySelector(`#prize-count-${type}`)
};
prizeElement[type] = elements;
}
if (!prizeElement.prizeType) {
prizeElement.prizeType = document.querySelector("#prizeType");
prizeElement.prizeLeft = document.querySelector("#prizeLeft");
prizeElement.prizeText = document.querySelector("#prizeText");
}
if (isInit) {
for (let i = prizes.length - 1; i > currentPrizeIndex; i--) {
let type = prizes[i]["type"];
document.querySelector(`#prize-item-${type}`).className =
"prize-item done";
document.querySelector(`#prize-bar-${type}`).style.width = "0";
document.querySelector(`#prize-count-${type}`).textContent =
"0" + "/" + prizes[i]["count"];
}
}
if (lasetPrizeIndex !== currentPrizeIndex) {
let lastPrize = prizes[lasetPrizeIndex],
lastBox = document.querySelector(`#prize-item-${lastPrize.type}`);
lastBox.classList.remove("shine");
lastBox.classList.add("done");
elements.box && elements.box.classList.add("shine");
prizeElement.prizeType.textContent = currentPrize.text;
prizeElement.prizeText.textContent = currentPrize.title;
lasetPrizeIndex = currentPrizeIndex;
}
if (currentPrizeIndex === 0) {
prizeElement.prizeType.textContent = "特别奖";
prizeElement.prizeText.textContent = " ";
prizeElement.prizeLeft.textContent = "不限制";
return;
}
count = totalCount - count;
count = count < 0 ? 0 : count;
let percent = (count / totalCount).toFixed(2);
elements.bar && (elements.bar.style.width = percent * 100 + "%");
elements.text && (elements.text.textContent = count + "/" + totalCount);
prizeElement.prizeLeft.textContent = count;
};
})();
function startMaoPao() {
let len = DEFAULT_MESS.length,
count = 5,
index = ~~(Math.random() * len),
danmuList = [],
total = 0;
function restart() {
total = 0;
danmuList.forEach(item => {
let text =
lastDanMuList.length > 0
? lastDanMuList.shift()
: DEFAULT_MESS[index++];
item.start(text);
index = index > len ? 0 : index;
});
}
for (let i = 0; i < count; i++) {
setTimeout(() => {
danmuList.push(
new DanMu({
text: DEFAULT_MESS[index++],
onComplete: function () {
setTimeout(() => {
this.start(DEFAULT_MESS[index++]);
index = index > len ? 0 : index;
}, 1000);
}
})
);
index = index > len ? 0 : index;
}, 1500 * i);
}
}
function addDanMu(text) {
lastDanMuList.push(text);
}
export {
startMaoPao,
showPrizeList,
setPrizeData,
addDanMu,
setPrizes,
resetPrize,
addQipao
};
const webpack = require("webpack");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const path = require("path");
module.exports = {
entry: path.join(__dirname, "/src/lottery/index.js"),
output: {
path: path.join(__dirname, "/dist"),
filename: "lottery.js"
},
module: {
rules: [
{
test: /(\.jsx|\.js)$/,
use: {
loader: "babel-loader"
},
exclude: /node_modules/
},
{
test: /\.css$/,
use: [
{
loader: "style-loader"
},
{
loader: "css-loader"
},
{
loader: "postcss-loader"
}
]
}
]
},
plugins: [
new webpack.BannerPlugin("版权所有,翻版必究"),
new HtmlWebpackPlugin({
template: path.join(__dirname, "/src/index.html"),
filename: "./index.html",
minify: {
// 移除空属性
removeEmptyAttributes: true,
// 压缩css
minifyCSS: true,
// 压缩JS
minifyJS: true,
// 移除空格
collapseWhitespace: true
},
hash: true,
inject: true
}),
new CopyWebpackPlugin([
{
from: "./src/css",
to: "./css"
},
{
from: "./src/data",
to: "./data"
},
{
from: "./src/img",
to: "./img"
},
{
from: "./src/lib",
to: "./lib"
}
])
]
};
const baseConfig = require("./webpack.config");
const merge = require("webpack-merge");
const serve = require("../server/server.js");
module.exports = merge(baseConfig, {
devtool: "#eval-source-map",
devServer: {
hot: true,
compress: true,
port: 9000,
open: true,
proxy: {
"*": "http://localhost:18888"
},
before() {
serve.run(18888, "n");
}
}
});
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "启动程序",
"program": "${workspaceFolder}\\index.js",
// "cwd": "D:\\Project\\MR9\\MR9\\dist"
// 调试路劲
"cwd": "C:\\Users\\Administrator\\Desktop\\end\\src"
}
]
}
\ No newline at end of file
/**
* 奖品设置
* type: 唯一标识,0是默认特别奖的占位符,其它奖品不可使用
* count: 奖品数量
* title: 奖品描述
* text: 奖品标题
* img: 图片地址
*/
const prizes = [
{
type: 0,
count: 1000,
title: "",
text: "特别奖"
},
{
type: 1,
count: 2,
text: "特等奖",
title: "神秘大礼",
img: "../img/secrit.jpg"
},
{
type: 2,
count: 5,
text: "一等奖",
title: "Mac Pro",
img: "../img/mbp.jpg"
},
{
type: 3,
count: 6,
text: "二等奖",
title: "华为 Mate30",
img: "../img/huawei.png"
},
{
type: 4,
count: 7,
text: "三等奖",
title: "Ipad Mini5",
img: "../img/ipad.jpg"
},
{
type: 5,
count: 8,
text: "四等奖",
title: "大疆无人机",
img: "../img/spark.jpg"
},
{
type: 6,
count: 8,
text: "五等奖",
title: "Kindle",
img: "../img/kindle.jpg"
},
{
type: 7,
count: 11,
text: "六等奖",
title: "漫步者蓝牙耳机",
img: "../img/edifier.jpg"
}
];
/**
* 一次抽取的奖品个数与prizes对应
*/
const EACH_COUNT = [1, 1, 5, 6, 7, 8, 9, 10];
/**
* 卡片公司名称标识
*/
const COMPANY = "InsCode";
module.exports = {
prizes,
EACH_COUNT,
COMPANY
};
const fs = require("fs");
const path = require("path");
const xlsx = require("node-xlsx").default;
let cwd = path.join(__dirname, "cache");
if (!fs.existsSync(cwd)) {
fs.mkdirSync(cwd);
}
/**
* 读取缓存的数据内容
*/
function loadTempData() {
let pros = [];
pros.push(
new Promise((resolve, reject) => {
fs.readFile(path.join(cwd, "temp.json"), "utf8", (err, data) => {
if (err) {
resolve({});
return;
}
resolve(JSON.parse(data));
});
})
);
pros.push(
new Promise((resolve, reject) => {
fs.readFile(path.join(cwd, "error.json"), "utf8", (err, data) => {
if (err) {
resolve([]);
return;
}
resolve(JSON.parse(data));
});
})
);
return Promise.all(pros);
}
/**
* 读取XML文件数据
*/
function loadXML(xmlPath) {
let userData = xlsx.parse(xmlPath);
let outData = [];
userData.forEach(item => {
outData = item.data;
outData.shift();
return false;
});
outData = outData.filter(item => item.length > 0);
return outData;
}
/**
* 写入excel
* @param {Array} data
* @param {string} name
*/
function writeXML(data, name) {
let buffer = xlsx.build([
{
name: "抽奖结果",
data: data
}
]);
return new Promise((resolve, reject) => {
fs.writeFile(path.join(process.cwd(), name), buffer, err => {
if (err) {
reject(err);
return;
}
resolve();
});
});
}
/**
* 写入文件
* @param {*} data
*/
function saveDataFile(data) {
data = JSON.stringify(data, "", 2);
if (!fs.existsSync(cwd)) {
fs.mkdirSync(cwd);
}
return new Promise((resolve, reject) => {
fs.writeFile(path.join(cwd, "temp.json"), data, err => {
if (err) {
reject(err);
return;
}
resolve();
console.log("数据写入成功");
});
});
}
/**
* 错误日志文件输出
* @param {*} data
*/
function saveErrorDataFile(data) {
data = JSON.stringify(data, "", 2);
if (!fs.existsSync(cwd)) {
fs.mkdirSync(cwd);
}
return new Promise((resolve, reject) => {
fs.writeFile(path.join(cwd, "error.json"), data, err => {
if (err) {
reject(err);
return;
}
resolve();
console.log("数据写入成功");
});
});
}
/**
* 洗牌算法
* @param {*} arr
*/
function shuffle(arr) {
let i = arr.length;
while (i) {
let j = Math.floor(Math.random() * i--);
let temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
module.exports = {
loadTempData,
loadXML,
shuffle,
writeXML,
saveDataFile,
saveErrorDataFile
};
#!/usr/bin/env node
require("./server.js").run.apply(null, process.argv.slice(2));
{
"name": "http-mini",
"version": "1.0.4",
"description": "a simple static web server base on Express",
"main": "index.js",
"bin": {
"http-mini": "index.js"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "moshang",
"repository": {
"type": "git",
"url": "git+https://github.com/moshang-xc/web-server.git"
},
"homepage": "https://github.com/moshang-xc/web-server#readme",
"license": "ISC",
"dependencies": {
"body-parser": "^1.18.2",
"chokidar": "^2.0.3",
"express": "^4.16.3",
"node-xlsx": "^0.12.1",
"opn": "^5.3.0"
}
}
const express = require("express");
const opn = require("opn");
const bodyParser = require("body-parser");
const path = require("path");
const chokidar = require("chokidar");
const cfg = require("./config");
const {
loadXML,
loadTempData,
writeXML,
saveDataFile,
shuffle,
saveErrorDataFile
} = require("./help");
let app = express(),
router = express.Router(),
cwd = process.cwd(),
dataBath = __dirname,
port = 8090,
curData = {},
luckyData = {},
errorData = [],
defaultType = cfg.prizes[0]["type"],
defaultPage = `default data`;
//这里指定参数使用 json 格式
app.use(
bodyParser.json({
limit: "1mb"
})
);
app.use(
bodyParser.urlencoded({
extended: true
})
);
if (process.argv.length > 2) {
port = process.argv[2];
}
app.use(express.static(cwd));
//请求地址为空,默认重定向到index.html文件
app.get("/", (req, res) => {
res.redirect(301, "index.html");
});
//设置跨域访问
app.all("*", function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By", " 3.2.1");
res.header("Content-Type", "application/json;charset=utf-8");
next();
});
app.post("*", (req, res, next) => {
log(`请求内容:${JSON.stringify(req.path, 2)}`);
next();
});
// 获取之前设置的数据
router.post("/getTempData", (req, res, next) => {
getLeftUsers();
res.json({
cfgData: cfg,
leftUsers: curData.leftUsers,
luckyData: luckyData
});
});
// 获取所有用户
router.post("/reset", (req, res, next) => {
luckyData = {};
errorData = [];
log(`重置数据成功`);
saveErrorDataFile(errorData);
return saveDataFile(luckyData).then(data => {
res.json({
type: "success"
});
});
});
// 获取所有用户
router.post("/getUsers", (req, res, next) => {
res.json(curData.users);
log(`成功返回抽奖用户数据`);
});
// 获取奖品信息
router.post("/getPrizes", (req, res, next) => {
// res.json(curData.prize);
log(`成功返回奖品数据`);
});
// 保存抽奖数据
router.post("/saveData", (req, res, next) => {
let data = req.body;
setLucky(data.type, data.data)
.then(t => {
res.json({
type: "设置成功!"
});
log(`保存奖品数据成功`);
})
.catch(data => {
res.json({
type: "设置失败!"
});
log(`保存奖品数据失败`);
});
});
// 保存抽奖数据
router.post("/errorData", (req, res, next) => {
let data = req.body;
setErrorData(data.data)
.then(t => {
res.json({
type: "设置成功!"
});
log(`保存没来人员数据成功`);
})
.catch(data => {
res.json({
type: "设置失败!"
});
log(`保存没来人员数据失败`);
});
});
// 保存数据到excel中去
router.post("/export", (req, res, next) => {
let type = [1, 2, 3, 4, 5, defaultType],
outData = [["工号", "姓名", "部门"]];
cfg.prizes.forEach(item => {
outData.push([item.text]);
outData = outData.concat(luckyData[item.type] || []);
});
writeXML(outData, "/抽奖结果.xlsx")
.then(dt => {
// res.download('/抽奖结果.xlsx');
res.status(200).json({
type: "success",
url: "抽奖结果.xlsx"
});
log(`导出数据成功!`);
})
.catch(err => {
res.json({
type: "error",
error: err.error
});
log(`导出数据失败!`);
});
});
//对于匹配不到的路径或者请求,返回默认页面
//区分不同的请求返回不同的页面内容
router.all("*", (req, res) => {
if (req.method.toLowerCase() === "get") {
if (/\.(html|htm)/.test(req.originalUrl)) {
res.set("Content-Type", "text/html");
res.send(defaultPage);
} else {
res.status(404).end();
}
} else if (req.method.toLowerCase() === "post") {
let postBackData = {
error: "empty"
};
res.send(JSON.stringify(postBackData));
}
});
function log(text) {
global.console.log(text);
global.console.log("-----------------------------------------------");
}
function setLucky(type, data) {
if (luckyData[type]) {
luckyData[type] = luckyData[type].concat(data);
} else {
luckyData[type] = Array.isArray(data) ? data : [data];
}
return saveDataFile(luckyData);
}
function setErrorData(data) {
errorData = errorData.concat(data);
return saveErrorDataFile(errorData);
}
app.use(router);
function loadData() {
console.log("加载EXCEL数据文件");
let cfgData = {};
// curData.users = loadXML(path.join(cwd, "data/users.xlsx"));
curData.users = loadXML(path.join(dataBath, "data/users.xlsx"));
// 重新洗牌
shuffle(curData.users);
// 读取已经抽取的结果
loadTempData()
.then(data => {
luckyData = data[0];
errorData = data[1];
})
.catch(data => {
curData.leftUsers = Object.assign([], curData.users);
});
}
function getLeftUsers() {
// 记录当前已抽取的用户
let lotteredUser = {};
for (let key in luckyData) {
let luckys = luckyData[key];
luckys.forEach(item => {
lotteredUser[item[0]] = true;
});
}
// 记录当前已抽取但是不在线人员
errorData.forEach(item => {
lotteredUser[item[0]] = true;
});
let leftUsers = Object.assign([], curData.users);
leftUsers = leftUsers.filter(user => {
return !lotteredUser[user[0]];
});
curData.leftUsers = leftUsers;
}
loadData();
module.exports = {
run: function(devPort, noOpen) {
let openBrowser = true;
if (process.argv.length > 3) {
if (process.argv[3] && (process.argv[3] + "").toLowerCase() === "n") {
openBrowser = false;
}
}
if (noOpen) {
openBrowser = noOpen !== "n";
}
if (devPort) {
port = devPort;
}
let server = app.listen(port, () => {
let host = server.address().address;
let port = server.address().port;
global.console.log(`lottery server listenig at http://${host}:${port}`);
// openBrowser && opn(`http://127.0.0.1:${port}`);
});
}
};
const fs = require("fs");
// 测试抽奖结果数据的正确性
var selected = {},
repeat = [],
luckyData = require("/Users/xiechang/Documents/project/抽奖/product/dist/temp.json"),
errorData = require("/Users/xiechang/Documents/project/抽奖/product/dist/error.json");
for (let key in luckyData) {
let item = luckyData[key];
item.forEach(user => {
let id = user[0];
if (selected[id]) {
repeat.push(user[1]);
return;
}
selected[id] = true;
});
}
errorData.forEach(user => {
let id = user[0];
if (selected[id]) {
repeat.push(user[1]);
return;
}
selected[id] = true;
});
if (repeat.length > 0) {
console.log(repeat);
return;
}
console.log("没有重复选项");
TAG=$1
docker tag lottery:latest panda1024/lottery:${TAG}
docker push panda1024/lottery:${TAG}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册