SOURCE

class NameCard {
    constructor({name}) {
        let el = document.createElement('div');
        el.classList.add('name-card');
        el.innerText = name;
        this.el = el;
    }

    lit(isOn) {
        this.el.classList[isOn ? 'add' : 'remove']('name-card--hit');
    }
}

class NameRandom {
    constructor() {
        let el = document.createElement('div');
        el.classList.add('name-random');

        let namesContainer = document.createElement('div');
        namesContainer.classList.add('names-container');
        this.namesContainer = namesContainer;
        el.appendChild(namesContainer);

        this.el = el;
        this.nameCards = [];
        this.lastLitIndex = 0;
        this.currLitIndex = 0;
    }

    loadNames(names) {
        this.nameCards.forEach((nameCard) => {
            nameCard.lit(false);
        });

        this.nameCards = [];
        names.forEach((name) => {
            let nameCard = new NameCard({name});
            this.nameCards.push(nameCard);
            this.namesContainer.appendChild(nameCard.el);
        });

        // 开始按钮
        let startButton = document.createElement('button');
        startButton.classList.add('start-button');
        startButton.innerText = '随机';
        startButton.addEventListener('click', this._onStartClick.bind(this));
        this.startButton = startButton;
        this.el.appendChild(startButton);
    }

    _onStartClick() {
        this.startButton.disabled = true;
        this.nameCards.forEach((nameCard) => {
            nameCard.lit(false);
        });
        let randomIndex = this._randInt(0, this.nameCards.length);

        this.animationTimer = setInterval(() => {
            this.nameCards[this.lastLitIndex].lit(false);
            this.currLitIndex++;
            this.currLitIndex = this.currLitIndex % this.nameCards.length;
            this.lastLitIndex = this.currLitIndex;
            this.nameCards[this.currLitIndex].lit(true);
            if (this.currLitIndex == randomIndex) {
                clearInterval(this.animationTimer);
                this.startButton.disabled = false;
            }
        }, 150);
    }

    // 随机返回m到n(不包括n)之间的数
    _randInt(m, n) {
        return Math.floor(Math.random() * (n - m)) + m;
    }
}

window.onload = function() {
    let names = [
        '杨金林',
        '杜月华',
        '郝淑贞',
        '李四',
        '宋功文',
        '喵喵',
        '王国忠',
        '陈启耀',
        '刘红'
    ];
    let nameRandom = new NameRandom();
    nameRandom.loadNames(names);
    document.body.appendChild(nameRandom.el);
};
html,body {
    margin: 0px;
    padding: 0px;
    width: 100%;
    height: 100%;
    background: #eee;
    font-family: '微软雅黑';
    font-size: 14px;
}

.name-random {
    margin: 0 auto;
    width: calc(100% - 20px);
}

.names-container {
    display: flex;
    justify-content: center;
    width: fit-content;
    margin-left: auto;
    margin-right: auto;
    margin-top: 20px;
    padding: 20px;
    border: 1px solid #999;
    border-radius: 4px;
}

.name-card {
    width: 60px;
    height: 60px;
    line-height: 60px;
    vertical-align: middle;
    text-align: center;
    border-radius: 60px;
    background: #fff;
    margin: 4px;
    transition: 0.1s all ease;
}

.name-card--hit {
    background: orange;
    box-shadow: 1px 1px 6px rgba(0,0,0,0.2);
    color: #fff;
}

.start-button {
    width: 100px;
    height: 40px;
    margin: 0 auto;
    margin-top: 8px;
    display: block;
    border-radius: 4px;
    outline: none;
}
console 命令行工具 X clear

                    
>
console