Skip to content

Instantly share code, notes, and snippets.

@motsu0
Last active February 2, 2023 13:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save motsu0/da8c3e4d96fc855306307f08dbe16d57 to your computer and use it in GitHub Desktop.
Save motsu0/da8c3e4d96fc855306307f08dbe16d57 to your computer and use it in GitHub Desktop.
#screen{
height: 500px;
border: 1px solid #333;
user-select: none;
background-color: #fff;
}
#screen-inner{
height: 100%;
display: flex;
justify-content: center;
position: relative;
}
#screen-main{
display: flex;
justify-content: center;
align-items: center;
font-size: 40px;
line-height: 60px;
text-align: center;
}
/* */
#bt-get,#bt-pre{
display: block;
padding: 10px 20px;
position: absolute;
bottom: 5%;
border-width: 2px;
font-size: 20px;
}
#bt-fullscreen{
display: block;
margin: 50px auto;
}
.bt-kuji{
box-sizing: border-box;
border: 1px solid #333;
border-radius: 4px;
background-color: #fff;
user-select: none;
cursor: pointer;
}
.bt-kuji:hover{
background-color: #ddd;
}
/* settings */
#setting-font{
width: 60px;
margin: 0 4px;
}
/* kuji */
.kuji-unit {
padding: 8px;
margin: 16px 0;
background-color: #eee;
}
.kuji-name{
width: 300px;
vertical-align: top;
}
.kuji-num{
width: 100px;
}
.kuji-keep{
transform: scale(1.5);
margin: 0 8px;
cursor: pointer;
}
.kuji-bt-del{
display: block;
margin-left: auto;
}
#bt-add-kuji{
display: block;
margin: 0 auto;
}
#area-save{
margin: 60px 0;
text-align: right;
}
/* */
#msg-box{
box-sizing: border-box;
width: 100%;
position: fixed;
bottom: 10px;
left: 0;
z-index: 1000;
text-align: center;
pointer-events: none;
}
#message{
display: inline-block;
box-sizing: border-box;
max-width: 90%;
padding: 10px 20px;
border: 2px solid #BF360C;
background-color: #FBE9E7;
color: #BF360C;
word-break: break-all;
opacity: 1;
pointer-events: auto;
}
#message.off{
opacity: 0;
transition: opacity 1s;
pointer-events: none;
}
/* */
.s-hide{
display: none;
}
.invisible{
visibility: hidden;
}
summary{
cursor: pointer;
}
<div id="screen">
<div id="screen-inner">
<div id="screen-main"></div>
<button id="bt-get" class="bt-kuji">くじを引く</button>
<button id="bt-pre" class="bt-kuji invisible">くじの準備</button>
</div>
</div>
<button id="bt-fullscreen" class="bt-kuji">全画面表示</button>
<h2>設定</h2>
<div id="settings">
<div class="setting-item">
文字の大きさ<input type="number" min="4" max="100" value="40" id="setting-font">px
</div>
</div>
<div id="kuji-area">
<div class="kuji-unit">
<div class="kuji-item">
名前:<textarea class="kuji-name" placeholder="くじの名前">1等
温泉旅行ペアチケット</textarea>
</div>
<div class="kuji-item">
残数:<input type="number" class="kuji-num" min="0" placeholder="0" value="1">
</div>
<div class="kuji-item">
<input type="checkbox" class="kuji-keep">残数を減らさない
</div>
<div class="kuji-item">
<button class="kuji-bt-del bt-kuji">この項目を消去</button>
</div>
</div>
<div class="kuji-unit">
<div class="kuji-item">
名前:<textarea class="kuji-name" placeholder="くじの名前">2等
人気家庭用ゲーム機</textarea>
</div>
<div class="kuji-item">
残数:<input type="number" class="kuji-num" min="0" placeholder="0" value="2">
</div>
<div class="kuji-item">
<input type="checkbox" class="kuji-keep">残数を減らさない
</div>
<div class="kuji-item">
<button class="kuji-bt-del bt-kuji">この項目を消去</button>
</div>
</div>
<div class="kuji-unit">
<div class="kuji-item">
名前:<textarea class="kuji-name" placeholder="くじの名前">3等
有名メーカー掃除機</textarea>
</div>
<div class="kuji-item">
残数:<input type="number" class="kuji-num" min="0" placeholder="0" value="3">
</div>
<div class="kuji-item">
<input type="checkbox" class="kuji-keep">残数を減らさない
</div>
<div class="kuji-item">
<button class="kuji-bt-del bt-kuji">この項目を消去</button>
</div>
</div>
<div class="kuji-unit">
<div class="kuji-item">
名前:<textarea class="kuji-name" placeholder="くじの名前">4等
商品券</textarea>
</div>
<div class="kuji-item">
残数:<input type="number" class="kuji-num" min="0" placeholder="0" value="4">
</div>
<div class="kuji-item">
<input type="checkbox" class="kuji-keep">残数を減らさない
</div>
<div class="kuji-item">
<button class="kuji-bt-del bt-kuji">この項目を消去</button>
</div>
</div>
<div class="kuji-unit">
<div class="kuji-item">
名前:<textarea class="kuji-name" placeholder="くじの名前">参加賞
ポケットティッシュ</textarea>
</div>
<div class="kuji-item">
残数:<input type="number" class="kuji-num" min="0" placeholder="0" value="5">
</div>
<div class="kuji-item">
<input type="checkbox" class="kuji-keep">残数を減らさない
</div>
<div class="kuji-item">
<button class="kuji-bt-del bt-kuji">この項目を消去</button>
</div>
</div>
</div>
<button id="bt-add-kuji" class="bt-kuji">くじを追加</button>
<div id="area-save" class="s-hide">
<button id="bt-save" class="bt-kuji">くじを保存</button>
<button id="bt-load" class="bt-kuji">保存したくじを呼び出す</button>
</div>
<div id="msg-box">
<div id="message" class="off">データを保存しました。</div>
</div>
const screen = document.getElementById('screen');
const screen_inner = document.getElementById('screen-inner');
const screen_main = document.getElementById('screen-main');
const bt_save = document.getElementById('bt-save');
const bt_load = document.getElementById('bt-load');
const bt_get = document.getElementById('bt-get');
const bt_pre = document.getElementById('bt-pre');
const bt_fullscreen = document.getElementById('bt-fullscreen');
const bt_add_kuji = document.getElementById('bt-add-kuji');
const setting_font = document.getElementById('setting-font')
const kuji_area = document.getElementById('kuji-area');
const kuji_unit = document.getElementsByClassName('kuji-unit');
const kuji_name = document.getElementsByClassName('kuji-name');
const kuji_num = document.getElementsByClassName('kuji-num');
const kuji_keep = document.getElementsByClassName('kuji-keep');
const kuji_bt_del = document.getElementsByClassName('kuji-bt-del');
const msg = document.getElementById('message');
const el_area_save = document.getElementById('area-save');
let playing = false;
let is_save_valid = false;
//リスナ
bt_fullscreen.addEventListener('click',()=>{
screen.requestFullscreen();
});
bt_get.addEventListener('click',getKuji);
bt_pre.addEventListener('click',prepareKuji);
setting_font.addEventListener('change',fontChange);
[...kuji_bt_del].forEach(el=>{
el.addEventListener('click',()=>{delKuji(el)});
});
bt_add_kuji.addEventListener('click',addKuji);
bt_save.addEventListener('click',saveData);
bt_load.addEventListener('click',loadData);
//
checkCookie();
function fontChange(){
const fs = (()=>{
const val = Number(setting_font.value);
if(isNaN(val)){
setting_font.value = 40;
return 40;
}else if(val<=0){
setting_font.value = 40;
return 40;
}else{
return val;
}
})();
screen_main.style.fontSize = fs + 'px';
screen_main.style.lineHeight = (fs*1.5) + 'px';
}
function getKuji(){
//初期処理
if(playing) return;
playing = true;
bt_get.classList.add('invisible');
//変数定義
const name_set = [];
const kuji_set = [];
let num = 0;
//くじセット作成
[...kuji_num].forEach((el,i)=>{
let val = Number(el.value);
if(isNaN(val)){
val = 0;
el.value = 0;
}else if(val<0){
val = 0;
el.value = 0;
}
if(val>0){
num+=val;
kuji_set.push([i,num,newline(kuji_name[i].value)]);
name_set.push(newline(kuji_name[i].value));
}
});
if(num==0){
//空っぽ
playing = false;
screen_main.textContent = 'くじが無くなりました';
bt_get.classList.remove('invisible');
return;
}
//抽選
const hit_num = randomMN(1,num);
const hit_id = (()=>{
for(let i=0;i<kuji_set.length;i++){
if(hit_num<=kuji_set[i][1]){
return kuji_set[i][0];
}
}
})();
//演出
const count_max = 40;
let count = 0;
let index = 0;
shuffle(name_set);
if(name_set.length==1) count = count_max;
const timer = setInterval(()=>{
if(count>=count_max){
clearInterval(timer);
screen_main.innerHTML = newline(kuji_name[hit_id].value);
if(!kuji_keep[hit_id].checked) kuji_num[hit_id].value = Number(kuji_num[hit_id].value) - 1;
bt_pre.classList.remove('invisible');
}else{
screen_main.innerHTML = name_set[index];
index++;
if(index>=name_set.length) index = 0;
}
count++;
},50);
}
function prepareKuji(){
playing = false;
screen_main.textContent = '';
bt_get.classList.remove('invisible');
bt_pre.classList.add('invisible');
}
function delKuji(el){
if(kuji_unit.length>1){
const index = [...kuji_bt_del].indexOf(el);
kuji_unit[index].remove();
}else{
msgBox('全てのくじを消去することはできません。');
}
}
function addKuji(){
const el = kuji_unit[kuji_unit.length-1].cloneNode(true);
const bt = el.getElementsByClassName('kuji-bt-del')[0];
bt.addEventListener('click',()=>{delKuji(bt)});
kuji_area.appendChild(el);
}
function msgBox(str){
msg.textContent = str;
msg.classList.remove('off');
setTimeout(()=>{
msg.classList.add('off');
},1000);
}
function newline(str){
str = str.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;')
.replace(/(\r\n|\r|\n)/g,'<br>');
return str;
}
function randomMN(m,n){
const d = Math.max(m,n)-Math.min(m,n);
return Math.floor(Math.random()*(d+1)+Math.min(m,n));
}
function shuffle(array){
for(let i=array.length-1;i>=1;i--){
const j = randomMN(0,i);
[array[j],array[i]] = [array[i],array[j]];
}
}
function checkCookie(){
const is_cookie_valid = navigator.cookieEnabled;
if(!is_cookie_valid){
is_save_valid = false;
return;
}
if(typeof window.localStorage===undefined){
is_save_valid = false;
return;
}
is_save_valid = true;
el_area_save.classList.remove('s-hide');
}
function saveData(){
if(!is_save_valid) return;
const data = [];
[...kuji_unit].forEach((el,i)=>{
data.push([kuji_name[i].value, kuji_num[i].value, kuji_keep[i].checked]);
});
const cookie = JSON.stringify(data);
localStorage.setItem('nandemo-kuji-kuji', cookie);
localStorage.setItem('nandemo-kuji-fs', setting_font.value);
msgBox('データを保存しました。');
}
function loadData(){
if(!is_save_valid) return;
const cookie = localStorage.getItem('nandemo-kuji-kuji');
if(cookie==null){
msgBox('保存されたデータがありません。');
return;
}
const data = JSON.parse(cookie);
const len = kuji_unit.length;
if(data.length>len){
//不足分追加
for(let i=1;i<=data.length-len;i++){
addKuji();
}
}else if(data.length<len){
//余剰分削除
for(let i=1;i<=len-data.length;i++){
delKuji(kuji_bt_del[0]);
}
}
data.forEach((d,i)=>{
kuji_name[i].value = d[0];
kuji_num[i].value = d[1];
kuji_keep[i].checked = d[2];
});
setting_font.value = localStorage.getItem('nandemo-kuji-fs');
fontChange();
msgBox('保存されたデータを呼び出しました。');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment