200行HTML+JavaScript实现年会抽奖程序


Posted in Javascript onJanuary 22, 2019

本文实例为大家分享了js实现年会抽奖程序的具体代码,供大家参考,具体内容如下

需求分析

1.多轮抽奖,每轮只有3个环节:展示奖品图,人名闪动,停止闪动确定中奖名单
2.中奖分级,例如试用期员工不能中二等奖或以上
3.每轮抽奖的中奖人数不同。每个人只能中一次奖
4.可临时加场,现场输入奖品名、数量。额外窗口输入,避免被观众看到修改过程。
5.本地记录每轮的奖品和中奖名单
6.全屏显示。不确定现场的屏幕分辨率,故核心部分固定1024*768,居中显示;背景拉伸铺满全屏。

200行HTML+JavaScript实现年会抽奖程序

技术选型

搞桌面程序第一时间就想到了这几个框架:Java Swing、Python Tkinter、C++ Qt、C# WPF。虽然都可行,但感觉开发不够便捷。而且谁知道年会现场那台电脑有没有对应的运行时库。

最后经同事给的灵感想到了用JavaScript做,选定了node-webkit,即nw.js。没有选electron是它需要搭开发环境。

既然连开发环境都懒得搭,那自然也用不了Vue、React、Angular。实际上也没必要,小学生才用牛刀杀鸡。

代码开源

开源在 年会抽奖程序 。文末会贴一下当前的版本,但以github上的为准。

使用方法
启动
Windows的启动方法:到 这里 下载node-webkit,解压出来,把代码的整个目录拖动到nwjs.exe上。

其它操作系统按官方说明做:

cd /path/to/your/app
/path/to/nw .

/path/to/nw is the binary file of NW.js. On Windows, it's nw.exe; On Linux, it's nw; On Mac, it's nwjs.app/Contents/MacOS/nwjs.

按键

  • f:切换全屏
  • 4:下一步。进入下一轮抽奖的展示奖品图片、进入名单滚动。
  • 空格:立刻停止名单滚动。即确定中奖人员。
  • 8:重新加载配置文件。主要用于临场增加奖项
  • 1:上一步,用来看看上个奖项的情况

核心文件说明

  • index.html:所有代码都在这
  • steps.json:流程配置文件,应该一看就懂。中奖后此文件会被修改,包含中奖名单。如果需要加奖项,不用退出程序,编辑完这个文件后按8就能重新加载配置,继续抽。
  • names.ini:人员名单与可中奖等级,等级数字越小表示可中更大的奖。中奖后此文件会被修改,删除已中奖的人

TODO

  • 启动的时候设置窗口大小和位置会闪动,可以做得体验好点,虽然没必要
  • 更多的可动态设置项
  • 启动方式还是有点别扭,可打包一下程序

代码

程序步骤说明:

1.调整窗口大小和位置
2.读取配置文件,得到人员名单和抽奖轮次信息
3.进入第1轮。通过按键4和空格进入下个环节
4.用state变量来记录状态:展示图片、滚动名单、显示中奖名单

html的部分:

<!DOCTYPE html>
<html>
 <head>
 <meta charset="utf-8">
 <script>
  var win = nw.Window.get()
  win.resizeTo(1024, 768)
  win.moveTo(0, 0)
 </script>
 <style type="text/css">
  * {
  margin: 0;
  padding: 0;
  }
  html, body {
  width: 100%;
  height: 100%;
  }
  body {
  text-align: center;
  background: url("./bg.png") no-repeat;
  overflow: hidden;
  background-size: 100% 100%;
  font-weight: bold;
  color: #D40000;
  }
  #container {
  min-width: 1000px;
  min-height: 700px;
  }
  #title {
  font-size: 100px;
  margin-top: 80px;
  }
  #disc {
  font-size: 40px;
  margin: 10px 0;
  }
  #image {
  margin-top: 20px;
  max-height: 280px;
  border: 1px solid #E23540FF;
  border-radius: 20px;
  }
  #list {
  margin: 0 auto;
  max-width: 800px;
  }
  #list span {
  display: inline-block;
  width: 160px;
  font-size: 36px;
  margin-top: 8px;
  }
 </style>
 </head>

 <body>
 <div id="container">
  <div id="title">XX公司年会</div>
  <div id="disc">奖品描述</div>
  <img id="image" />
  <div id="list"></div>
 </div>
 <script>
  var fs = require('fs')
  var steps = null
  var step = 0
  var names = null
  var state = ''
  
  var disc = document.getElementById('disc')
  var image = document.getElementById('image')
  var list = document.getElementById('list')

  function reloadConf(func) {
  fs.readFile('names.ini', 'utf8', function(err, data) {
   names = data.split('\n').map(x => x.split(','))
  })
  fs.readFile('./steps.json', 'utf8', function(err, data) {
   steps = eval(data)
   if (func) func()
  })
  }

  function saveConf(func) {
  fs.writeFile('./steps.json', JSON.stringify(steps), function(err) {
   if (err) {
   alert(err)
   }
  })
  fs.writeFile('./names.ini', names.map(x => x.join(',')).join('\n'), function(err) {
   if (err) {
   alert(err)
   }
  })
  }

  function showPic(data) {
  disc.innerHTML = data.disc
  image.src = data.image
  image.style.display = 'inline'
  list.style.display = 'none'
  while (list.hasChildNodes()) {
   list.removeChild(list.firstChild)
  }
  }

  function showBlink(data) {
  disc.innerHTML = data.disc
  image.style.display = 'none'
  list.style.display = 'block'
  var spans = []
  for (var i = 0; i < data.count; ++i) {
   var span = document.createElement('span')
   list.appendChild(span)
   spans.push(span)
  }

  function doBlink() {
   if (state == 'showBlink') {
   names.sort(function() {
    return 0.5 - Math.random()
   })
   for (var i = 0; i < data.count; ++i) {
    spans[i].innerHTML = names[i][0]
   }
   window.requestAnimationFrame(doBlink)
   }
  }

  window.requestAnimationFrame(doBlink)
  }

  function showList(data) {
  disc.innerHTML = data.disc
  image.style.display = 'none'
  list.style.display = 'block'
  while (list.hasChildNodes()) {
   list.removeChild(list.firstChild)
  }
  for (var i = 0; i < data.list.length; ++i) {
   var span = document.createElement('span')
   span.innerHTML = data.list[i]
   list.appendChild(span)
  }
  }

  function nextStep() {
  var data = steps[step]
  if (state == 'showPic') {
   data.list = data.list || []
   if (data.list.length > 0) {
   state = 'showList'
   showList(data)
   } else {
   state = 'showBlink'
   showBlink(data)
   }
  } else if (state == 'showBlink') {
   if (data.list.length > 0) {
   state = 'showList'
   showList(data)
   }
  } else if (state == 'showList') {
   if (step < (steps.length - 1)) {
   ++step
   state = ''
   nextStep()
   }
  } else {
   state = 'showPic'
   showPic(data)
  }
  }

  function previousStep() {
  if (step > 0) {
   --step
  }
  state = ''
  nextStep()
  }

  function drawPrize() {
  if (state == 'showBlink') {
   var data = steps[step]
   names.sort(function (a, b) {
   if (a[1] <= data.level && b[1] > data.level) {
    return -1
   }
   return 0
   })
   var luck = names.splice(0, data.count)
   data.list = luck.map(x => x[0])
   saveConf()
   nextStep()
  }
  }

  document.addEventListener('keydown', function(e) {
  e=e||window.event
  if (e.keyCode == 56) {
   // 8
   reloadConf()
  } else if (e.keyCode == 52) {
   // 4
   nextStep()
  } else if (e.keyCode == 49) {
   // 1
   previousStep()
  } else if (e.keyCode == 32) {
   // 空格
   drawPrize()
  } else if (e.keyCode == 70) {
   // f
   win.toggleFullscreen()
  }
  })
  
  reloadConf(nextStep)
 </script> 
 </bdoy>
</html>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
在页面上用action传递参数到后台出现乱码的解决方法
Dec 31 Javascript
javascript记录文本框内文字个数检测文字个数变化
Oct 14 Javascript
使用node.js 获取客户端信息代码分享
Nov 26 Javascript
浅谈javascript实现八大排序
Apr 27 Javascript
大型JavaScript应用程序架构设计模式
Jun 29 Javascript
微信小程序 欢迎界面开发的实例详解
Nov 30 Javascript
Three.js的使用及绘制基础3D图形详解
Apr 27 Javascript
vuex的简单使用教程
Feb 02 Javascript
微信小程序开发之tabbar图标和颜色的实现
Oct 17 Javascript
vue router带参数页面刷新或回退参数消失的解决方法
Feb 27 Javascript
通过微信公众平台获取公众号文章的方法示例
Dec 25 Javascript
解决vue $http的get和post请求跨域问题
Jun 07 Vue.js
微信小程序使用map组件实现获取定位城市天气或者指定城市天气数据功能
Jan 22 #Javascript
微信小程序使用map组件实现解析经纬度功能示例
Jan 22 #Javascript
微信小程序全局变量功能与用法详解
Jan 22 #Javascript
微信小程序使用map组件实现路线规划功能示例
Jan 22 #Javascript
JavaScript JMap类定义与使用方法示例
Jan 22 #Javascript
vue2.0 如何在hash模式下实现微信分享
Jan 22 #Javascript
JavaScript继承与聚合实例详解
Jan 22 #Javascript
You might like
德劲1104的电路分析与改良
2021/03/01 无线电
数组任意位置插入元素,删除特定元素的实例
2017/03/02 PHP
php使用 readfile() 函数设置文件大小大小的方法
2017/08/11 PHP
Javascript 继承机制的实现
2009/08/12 Javascript
数组方法解决JS字符串连接性能问题有争议
2011/01/12 Javascript
基于jquery的button默认enter事件(回车事件)。
2011/05/18 Javascript
js返回上一页并刷新代码整理
2012/12/21 Javascript
jquery禁止回车触发表单提交
2014/12/12 Javascript
JavaScript检查弹出窗口是否被阻拦的方法技巧
2015/03/13 Javascript
yui3的AOP(面向切面编程)和OOP(面向对象编程)
2015/05/01 Javascript
微信小程序 实现点击添加移除class
2017/06/12 Javascript
js中null与空字符串&quot;&quot;的区别讲解
2019/01/17 Javascript
vue 中 beforeRouteEnter 死循环的问题
2019/04/23 Javascript
记一次vue跨域的解决
2020/10/21 Javascript
[01:43]深扒TI7聊天轮盘语音出处4
2017/05/11 DOTA
Python创建系统目录的方法
2015/03/11 Python
在Django的模板中使用认证数据的方法
2015/07/23 Python
Python安装第三方库及常见问题处理方法汇总
2016/09/13 Python
Python3 加密(hashlib和hmac)模块的实现
2017/11/23 Python
Python使用Django实现博客系统完整版
2020/09/29 Python
python3+PyQt5 自定义窗口部件--使用窗口部件样式表的方法
2019/06/26 Python
python 检测nginx服务邮件报警的脚本
2020/12/31 Python
德国价格合理的品牌商品购物网站:averdo
2019/03/21 全球购物
日本化妆品植村秀俄罗斯官方网站:Shu Uemura俄罗斯
2020/02/01 全球购物
自荐书模板
2013/12/19 职场文书
加拿大留学自荐信
2014/01/28 职场文书
《得道多助,失道寡助》教学反思
2014/04/19 职场文书
五心教育心得体会
2014/09/04 职场文书
信用卡逾期证明示例
2014/09/13 职场文书
个人存款证明书
2014/10/18 职场文书
趣味运动会开幕词
2015/01/28 职场文书
2015年纪念“卢沟桥事变”78周年活动方案
2015/05/06 职场文书
导游词之宿迁乾隆行宫
2019/10/15 职场文书
想创业成功,需要掌握这些要点
2019/12/06 职场文书
Mysql忘记密码解决方法
2022/02/12 MySQL
Python列表的索引与切片
2022/04/07 Python