点名系统实现

演示: http://lu-renjiajia.gitee.io/random-roll-call

1.静态页面部分

主要采用css的弹性布局flex;

html代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport"
    content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no" />
  <title>♥♥♥♥♥辛♥♥♥♥♥</title>
  <link href="./favicon(2).ico" rel="shortcut icon" type="image/x-icon" />
  <link rel="stylesheet" href="./css/index.css">
  <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
</head>
<body>
  <h1>被选中的小伙伴们:</h1>
  <div class="ll">
  <select class="lxx" name="" id="aselect">
    <option value="5">5秒</option>
    <option value="10">10秒</option>
    <option value="15">15秒</option>
    <option value="20">20秒</option>
  </select>
  <button class="lxx">开始</button>
  <input class="lxx" type="text" id="personNum" value="1">
  </div>
  <ul></ul>
  <audio id="aut" src="./audio/自定义语言包.mp3" style="width: 0;"></audio>
</body>
<script src="./js/index.js"></script>
</html>

css代码:

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }

  body {
    padding: 20px 0px;
    background: url(../img/11.webp);
    background-size: cover;
    background-position: center top;
    background-repeat: no-repeat;

  }
  @media screen and (max-width:750px){
    body {
    background: url(../img/bg.webp);
    /* background-size: 100%; */
    background-size:cover;
    background-position: center top;
    background-repeat: no-repeat;
  }
  }
  h1 {
    padding: 10px;
    background-color: #327dcd;
    color: purple;
    /* margin: 10px 0; */
    transition: all 1s;
    text-align: center;
  }
  ul {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    justify-content: space-around;
    overflow: hidden;
  }

  li {
    width: 100px;
    height: 40px;
    background-color: rgb(71, 134, 222);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 10px;
  }
  /* 确定下来了 最终被选中 */
  .select {
    background-color: palevioletred;
    color: #fff;
  }
  .lxx{
    width: 100px;
    height: 50px;
    color: #fff;
    border: none;
    font-size: 20px;
    background: rgb(14, 149, 161);
    box-shadow: 40px 40px 80px rgb(71, 134, 222),
      -40px -40px 80px rgb(71, 134, 222);
      text-align: center;
      cursor: pointer;
  }
  .lxx:hover{
    background-color: rgb(11, 82, 181);
  }
  .ll{
    display: flex;
    justify-content: space-around;
    align-items: center;
    margin-top: 20px;
  }
  #personNum{
    height: 30px;
  }
  #aselect{
    height: 30px;
  }

2.功能实现

功能1:渲染名单到页面;

思路:即已拿到了字符串名称;

可以通过字符串的split()方法来通过特定的字符来把字符串转换为数组;

代码如下:

const str = '张国颖 邱成武 谢晓华 廖浩然 窦广灿 陈泽锋 蓝湘杰 陈锦田 陈天培 王德怀 吴柏奇 李远宁 颜石伟 梁品鑫 范名杰 刘婷 梁海龄 戴嘉琪 张雄杰 潘科华 马汉文 邓嘉豪 周康凯 刘森琪 张阳 徐君豪 黄俊博 张家凤 周日禧 黄善桥 蓝梓豪 劳政永 林泓森 秦柏林 薛岩 张旭东 钟世添 严文聪 余家凯 莫志俊 白丽臣 邱宗焕 梁碧燕 陈秋歌 黄光衡 侯正铭 刘辛 刘新勇 廖锦龙 谢文坚 曾子杭 滕飞 姚鑫涛 林蔚坤 彭奕安 廖有金 刘皓天 陈凯麟 陈巧 荣棒 莫格云 黄伟龙 阙娟 苏彩 陈星 金金亮 黎梓烨 刘松 丘翠娴 彭玉馨 肖根钦 陈冠锦 刘庆邦 曾海龙 谢伟平 刘文辉 于延杰';

接下来把拿到的数组进行页面渲染;通过反引号${}来获取值,在通过innerHTML来添加进入我们要的标签当中

let xuanRan = () => {
    let liHTML = "";
    for (let i = 0; i < arr.length; i++) {
        liHTML += `
          <li>${arr[i]}</li>
        `
    }
    ul.innerHTML = liHTML;
}

功能2:需要一个随机函数,

通过Math对象里面的Math.random()方法!!!

let getRandom=(max, min)=>{
    return Math.floor(Math.random() * (max - min + 1) + min);
}

功能3:随机抽取幸运观众

思路,先从整个数组中,抽取我定义的人的个数,把这些人存入一个数组,并返回,slice(x)可以从x下标开始,截取从该下标开始的到数组末尾的整个数组,并返回;

let myRandomArr = (arrList, num) => {
    if (num > arrList.length) {
        return;
    } else {
        let tempArr = arrList.slice(0);
        let newArrList = [];
        for (let i = 0; i < num; i++) {
            let random =     getRandom(tempArr.length - 1, 0);
            let arr = tempArr[random];
            tempArr.splice(random, 1);
            newArrList.push(arr);
        }
        return newArrList;
    }
}

值得一提的是,我需要改变原数组的内容,保证我页面已经渲染到的,被选出来的元素,不在被选中,我这采用了过滤操作,返回被选中的数组之外的元素,并重新赋值给原数组

for (let j = 0; j < choice.length; j++) {
            arr = arr.filter(item => item != choice[j]);
        }

功能4:把我抽取的数组进行样式的添加和渲染到结果和标签中

思路:通过对整个数组的

for (let j = 0; j < choice.length; j++) {
                if (lis[i].innerText === choice[j]) {
                    lis[i].classList.add("select");
                }
            }

遍历,先通过排他思想把所有的li的select类清除掉

其次我还有保留我上次选中的li的select不被清楚

思路:通过页面中span标签里面的innerTetx来与li中每一个进行对比,如果存在,那么在全部清除样式后在把这个加上

 for (let j = 0; j < spans.length; j++) {
                if (spans[j].innerText === lis[i].innerText) {
                    lis[i].classList.add("select");
                }
            }

说明:另一种思路,就是在排他时是就进行判定,如果存在,则不删这个,使用continue跳出本次循环;(这里就不写代码了);

功能5:为了保证我们能个一直产生随机数,一直随机抽取,我们需要一个定时器

思路,把功能四放进一个定时器里面,时间参数,为我们在自定义的时间(随机抽取的速度)。即可

timer = setInterval(() => {
    //功能4
,时间}

功能6:我们需要设置随机抽取的结束时间

思路:设置一个延时器,结束时间为我们在外面获取的自定义设置的时间;然后再延时器里面清除定时器;然后重新渲染我们选中人后添加了select样式的页面;

setTimeout(() => {
        clearInterval(timer);
        xuanRanPerson();
    }, time1 * 1000)

功能7:渲染我们抽中的人,加上select类后的样式页面

思路:通过insertAdjacentHTML()来进行添加,beforeend表示在子元素的末尾加,反引号``添加标签

let xuanRanPerson = () => {
        for (let i = 0; i < choice.length; i++) {
            h1.insertAdjacentHTML("beforeend",
                `
            <span>${choice[i]}</span>
           `)
        }
    }

功能8:修改h1文字的颜色,随机变色

思路:通过rgb的三个值0-255,可以用随机数范围在0-255,随机生成三个数给三个参数,q,w,e;通过style去修改

let q, w, e;
setInterval(() => {
    q = getRandom(255, 0);
    w = getRandom(255, 0);
    e = getRandom(255, 0);
    h1.style.color = `rgb(${q},${w},${e})`
}, 1000)

功能9:谷歌浏览器的语音播报

思路:通过SpeechSynthesisUtterance对象来操作,为了保证每次读的不会重复上次抽取到的人,每次播报完后进行置空,加“,”使浏览器阅读一个名字后,会暂停一秒;

let bobao = () => {
    let text = namearr.join(",");
    let msg = new SpeechSynthesisUtterance(text);
    msg.rate = 0.3;
    msg.pitch = 1;
    msg.volume = 1;
    speechSynthesis.speak(msg);
    text = "";
    namearr = [];
}

功能10:开始按钮的语音播报

思路:自己找al语音助手生成的语音,并录制下来,然后转为MP4格式,在利用audio的方法play(),pause()来进行控制

let audioPlay = () => {
    let aut = document.querySelector("#aut");
    if (aut !== null) {
        if (aut.paused) {
            aut.play();
        } else {
            aut.pause();
        }
    }
}

优化1:为了保证我点击按钮后不会触发第二定时器,使页面混乱;

思路:1.我在开启定时器之前,关闭定时器;

2:直接点击按钮后,把按钮禁用,只有延时器开始后,关闭定时器的时候,在把按钮启用;

优化2:对于自定义的人数,规定1-20人

源码:

js:

const str = '张国颖 邱成武 谢晓华 廖浩然 窦广灿 陈泽锋 蓝湘杰 陈锦田 陈天培 王德怀 吴柏奇 李远宁 颜石伟 梁品鑫 范名杰 刘婷 梁海龄 戴嘉琪 张雄杰 潘科华 马汉文 邓嘉豪 周康凯 刘森琪 张阳 徐君豪 黄俊博 张家凤 周日禧 黄善桥 蓝梓豪 劳政永 林泓森 秦柏林 薛岩 张旭东 钟世添 严文聪 余家凯 莫志俊 白丽臣 邱宗焕 梁碧燕 陈秋歌 黄光衡 侯正铭 刘辛 刘新勇 廖锦龙 谢文坚 曾子杭 滕飞 姚鑫涛 林蔚坤 彭奕安 廖有金 刘皓天 陈凯麟 陈巧 荣棒 莫格云 黄伟龙 阙娟 苏彩 陈星 金金亮 黎梓烨 刘松 丘翠娴 彭玉馨 肖根钦 陈冠锦 刘庆邦 曾海龙 谢伟平 刘文辉 于延杰';
let arr = str.split(" ");
let ul = document.querySelector("ul");
let btn = document.querySelector("button");
let timer; let time1;let xiaoid;
let namearr = []; let choice=[]; let data = [];
let h1 = document.querySelector("h1");
let personNum = document.querySelector("#personNum");
//渲染页面
let xuanRan = () => {
    let liHTML = "";
    for (let i = 0; i < arr.length; i++) {
        liHTML += `
          <li>${arr[i]}</li>
        `
    }
    ul.innerHTML = liHTML;
}
//调用
xuanRan();
//添加点击事件
btn.addEventListener("click", (e) => {
    //清除定时器,延时器
    clearInterval(timer);
    clearTimeout(xiaoid)
    let lis = document.querySelectorAll("li");
    let aselect = document.querySelector("#aselect");
    let pernum = parseInt(personNum.value);
    let spans = document.querySelectorAll("span") || null;
    time1 = parseInt(aselect.value);
    //语音提示播报
    if (pernum > arr.length) {
        let str='您好,数据过大,查询人数不得大于候选的人数';
        alert('您好,数据过大,查询人数不得大于候选的人数')
        bobao(str);
        btn.disabled = false;
        return;
    }else if(pernum===0){
        let str='您好,要查询的人数不能为0';
        alert('您好,要查询的人数不能为0');
        bobao(str);
        btn.disabled = false;
        return;
    }
    else if (pernum > 20) {
        let str='您好,不能一次性查找20人以上';
        alert('您好,不能一次性查找20人以上');
        bobao(str);
        btn.disabled = false;
        return;
    } else {
        //调用开始的音频
        audioPlay();
        timer = setInterval(() => {
            //从候选名单内获取长度为pernum的不重复数组
            choice = myRandomArr(arr, pernum);
            //先把所有的li的样式去掉
            for (let i = 0; i < lis.length; i++) {
                lis[i].classList.remove("select");
                for (let j = 0; j < spans.length; j++) {
                    //已选中的,且渲染在span标签里面的样式加回来
                    if (spans[j].innerText === lis[i].innerText) {
                        lis[i].classList.add("select");
                    }
                }
                //被选中的人加上样式
                for (let j = 0; j < choice.length; j++) {
                    if (lis[i].innerText === choice[j]) {
                        lis[i].classList.add("select");
                    }
                }
            }
        }, 50);
        //延时器,延时time1*1000  秒后清除定时器  time1为我页面设置时间
        xiaoid=setTimeout(() => {
            //用于语音播报的数组添加我选中的人
            for (let i = 0; i < choice.length; i++) {
                namearr.push(choice[i]);
            }
            //创参数调用播报函数
            bobao(namearr);
            //防止我选中的人在此被选中,把我选中的数组外的人从新赋值给原数组
            for (let j = 0; j < choice.length; j++) {
                arr = arr.filter(item => item != choice[j]);
            }
            btn.disabled = false;
            clearInterval(timer);
            //渲染被选中,加上样式的人
            xuanRanPerson();
        }, time1 * 1000)
    }
});
//渲染被选中,加上样式的人
let xuanRanPerson = () => {
    for (let i = 0; i < choice.length; i++) {
        h1.insertAdjacentHTML("beforeend",
            `
        <span>${choice[i]}</span>
       `)
    }
}
//获取随机数
let getRandom=(max, min)=> {
    return Math.floor(Math.random() * (max - min + 1) + min);
}
//生成rgb的三个参数
let q, w, e;
setInterval(() => {
    q = getRandom(255, 0);
    w = getRandom(255, 0);
    e = getRandom(255, 0);
    h1.style.color = `rgb(${q},${w},${e})`
}, 1000)
//随机抽取不重复的数组
let myRandomArr = (arrList, num) => {
    if (num > arrList.length) {
        return;
    } else {
        let tempArr = arrList.slice(0);
        let newArrList = [];
        for (let i = 0; i < num; i++) {
            let random = getRandom(tempArr.length - 1, 0);
            let arr = tempArr[random];
            tempArr.splice(random, 1);
            newArrList.push(arr);
        }
        return newArrList;
    }
}
//音频的开关
let audioPlay = () => {
    let aut = document.querySelector("#aut");
    if (aut !== null) {
        if (aut.paused) {
            aut.play();
        } else {
            aut.pause();
        }
    }
}
//语音播报
let bobao = (a) => {
    let text;
    if(a instanceof Array){
        text = a.join(",");
    }else if(1||str){
        text=a;
    }
    let msg = new SpeechSynthesisUtterance(text);
    console.log(text);
    msg.rate = 0.6;
    msg.pitch = 1;
    msg.volume = 1;
    speechSynthesis.speak(msg);
    text = "";
    namearr = [];
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值