200行HTML+JavaScript實現(xiàn)年會抽獎程序
本文實例為大家分享了js實現(xiàn)年會抽獎程序的具體代碼,供大家參考,具體內容如下
需求分析
1.多輪抽獎,每輪只有3個環(huán)節(jié):展示獎品圖,人名閃動,停止閃動確定中獎名單
2.中獎分級,例如試用期員工不能中二等獎或以上
3.每輪抽獎的中獎人數(shù)不同。每個人只能中一次獎
4.可臨時加場,現(xiàn)場輸入獎品名、數(shù)量。額外窗口輸入,避免被觀眾看到修改過程。
5.本地記錄每輪的獎品和中獎名單
6.全屏顯示。不確定現(xiàn)場的屏幕分辨率,故核心部分固定1024*768,居中顯示;背景拉伸鋪滿全屏。
技術選型
搞桌面程序第一時間就想到了這幾個框架:Java Swing、Python Tkinter、C++ Qt、C# WPF。雖然都可行,但感覺開發(fā)不夠便捷。而且誰知道年會現(xiàn)場那臺電腦有沒有對應的運行時庫。
最后經(jīng)同事給的靈感想到了用JavaScript做,選定了node-webkit,即nw.js。沒有選electron是它需要搭開發(fā)環(huán)境。
既然連開發(fā)環(huán)境都懶得搭,那自然也用不了Vue、React、Angular。實際上也沒必要,小學生才用牛刀殺雞。
代碼開源
開源在 年會抽獎程序 。文末會貼一下當前的版本,但以github上的為準。
使用方法
啟動
Windows的啟動方法:到 這里 下載node-webkit,解壓出來,把代碼的整個目錄拖動到nwjs.exe上。
其它操作系統(tǒng)按官方說明做:
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就能重新加載配置,繼續(xù)抽。
- names.ini:人員名單與可中獎等級,等級數(shù)字越小表示可中更大的獎。中獎后此文件會被修改,刪除已中獎的人
TODO
- 啟動的時候設置窗口大小和位置會閃動,可以做得體驗好點,雖然沒必要
- 更多的可動態(tài)設置項
- 啟動方式還是有點別扭,可打包一下程序
代碼
程序步驟說明:
1.調整窗口大小和位置
2.讀取配置文件,得到人員名單和抽獎輪次信息
3.進入第1輪。通過按鍵4和空格進入下個環(huán)節(jié)
4.用state變量來記錄狀態(tài):展示圖片、滾動名單、顯示中獎名單
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>
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
ymPrompt的doHandler方法來實現(xiàn)獲取子窗口返回值的方法
今天在寫頁面時用到了ymPrompt的win方法來彈出一個窗口。由于要用到獲取子窗口返回來的值判斷是否刷新父窗口,在ymPrompt的組件Demo中一直沒有找到合適的方法實現(xiàn)2010-06-06關閉頁面window.location事件未執(zhí)行的原因及解決方法
這篇文章主要介紹了關閉頁面window.location事件未執(zhí)行的原因及解決方法,需要的朋友可以參考下2014-09-09JavaScript正則函數(shù)中test和match的區(qū)別解析
在javascript中,用于檢測一個字符串是否匹配某個模式用的比較多的就是test和match方法。,這篇文章主要介紹了js正則函數(shù)中test和match的區(qū)別,需要的朋友可以參考下2022-11-11基于substring()和substr()的使用以及區(qū)別(實例講解)
下面小編就為大家分享一篇基于substring()和substr()的使用以及區(qū)別實例講解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12