likes
comments
collection
share

『 JS真好玩』关于我用原生 JS 实现一个有趣的抽奖程序😁

作者站长头像
站长
· 阅读数 12

前言

很久都没有用原生 JS 写过东西了,目前在实际开发中,基本都是用到现成的框架。刚好最近在小破站又学到了一个新的效果,同时也为了不遗忘原生 JS 相关的操作,今天我们就一起来使用原生 JS 开发一个抽奖的小程序。老规矩还是先看一下最终的成品吧,如下:

『 JS真好玩』关于我用原生 JS 实现一个有趣的抽奖程序😁

这个抽奖的程序很简单,刚打开的时候会自动旋转进行抽奖,当我们按下键盘的空格键时就会自动抽出当前的中奖人员。下面就让我们一起来看一下这个程序是如何实现的吧!

圆盘

首先我们需要先实现一下这个圆盘,这里只使用了简单的 htmlcss,让我们一起来看一下相关的代码,如下:

<div class="list"></div>

html 的内容很简单,只有一个 div 标签。我们再一起来看一下相关的 css 代码,如下:

*{
    margin: 0;
    padding: 0;
}
body {
    width: 100%;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #333;
    overflow: hidden;
}
.list {
    width: 400px;
    height: 400px;
    border: 1px solid #fff;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
}

上述的 css 就实现了一个圆,接下来我们需要设置一下在圆中右侧的中奖红三角,也是用 css 来实现的。那么你知道如何用纯 css 实现一个三角吗?让我们一起来看一下代码:

.list::after {
    content: '';
    position: absolute;
    width: 0;
    height: 0;
    border-width: 6px;
    border-style: solid;
    border-color: transparent transparent transparent red;
    right: 0;
}

css 中,我们可以通过 border 来创建一个三角形,只需要给对于的元素设置它的 widthheight 属性为 0,然后设置对应的 border 属性,如果你希望设置一个向右的三角形,那么你可以通过设置 border-color 来实现。border-color 可以设置四个值,这四个值分别对应的就是边框的上右下左,我们只需设置上右下三个边的颜色为透明的,给左边的边设置一个颜色,就能实现向右的三角行。同理,如果改变其中某个边的颜色,就能实现朝向其它方向的三角形,大家可以尝试一下。

实现了指向中奖人员的名单,我们接下来就实现一下圆圈周围的人名样式,相关代码如下:

.list::before {
    content: attr(data);
    position: absolute;
    color: #1e90ff;
    font-size: 64px;
}
.list span {
    color: #fff;
    position: absolute;
    width: calc(100% + 120px);
    height: 20px;
    text-align: right;
    transition: 0.01s linear;
    user-select: none;
}

我们给 listbefore 伪类添加了一个 attr(data) 值,这是为了后续在圆的中心显示当前指向中奖的人的名字,这个属性需要配合 JS 中的 setAttributes 方法一起使用,后续遇到再说这里。

静态的圆已经画好了,接下来我们就需要用到原生 JS 来实现人名的动态生成和抽奖了。

抽奖

因为我们这里是用原生 JS 来实现这个效果,因此我们所有的操作方法都是原生的方法。首先我们需要获取到 list 这个对象,我们可以通过 document.getElementsByClassName()document.querySelector() 来获取元素,这里我们用 document.querySelector(),因为它选取到的元素只是一个,如果用 document.getElementsByClassName(),我们还需要选择第一个元素。这两个 API 的区别,有想了解的童鞋可以到 MDN 官网去进行查看。

选择了 list 元素后,我们就需要动态的插入一些 span 标签了,这些 span 标签就是我们在圆周围展示的人名,而人名我们也是随机生成的。下面我们一起来看一下初始的代码,这里使用的也是面向对象的方式,代码如下:

class Lottery {
    constructor() {
        this.list = document.querySelector('.list');
        this.randomSurnam = ["赵", "钱", "孙", "李", "周", "吴", "郑", "王", "冯", "陈", "褚", "卫", "蒋", "沈", "韩", "杨"];
        this.randomName = ["泽", "桐", "梓", "一", "宁", "梅", "生", "平", "明", "涵", "韵", "宸", "坤", "华", "星", "家"];
        this.names = [];
        this.run = true;
        this.deg = 0;
        this.slow = 0;
    }
}

在 Lottery 类的构造函数中,我们定义了初始的属性,其中定义了一个随机的姓的数组和随机的名字的数字,我们通过这两个数字来动态的生成随机名字,接下来有一个初始化的方法,用于生成随机名字,代码如下:

class Lottery {
    constructor() {
        //...other code
        
        this.init();
    }
    
    init() {
        for (let i = 0; i < 40; i++) {
            this.names.push(
                this.randomSurnam[Math.random() * this.randomSurnam.length | 0] +
                this.randomName[Math.random() * this.randomName.length | 0] +
                this.randomName[Math.random() * this.randomName.length | 0]
            )
        }

        for (let key in this.names) {
            let span = document.createElement('span');
            span.innerText = this.names[key];
            this.list.appendChild(span);
        }
    }
}

初始化的数据准备好了,在上述的代码中,我们通过 document.createElement() 这个原生的 API 创建了一个 span 标签,然后通过 appendChild() 方法将 span 标签插入到对应的元素中。这两个 DOM 的操作方法是我们最初学习 JS 时最早接触到的方法。

接下来我们就需要通过 JS 将每一个 span 标签的位置固定在圆的周围了,让我们一起来看相关的代码,如下:

class Lottery {
    //...other code
    
    draw() {
        const spans = this.list.children;
        for (let i = 0; i < spans.length; i++) {
            let span = spans[i];
            span.style.transform = `rotate(${i / this.names.length * 360 + this.deg}deg)`;
            span.style.color = '#fff';
        }
        const now = ((360 - this.deg) / 360 * this.names.length | 0) % this.names.length;
        this.list.setAttribute('data', this.names[now]);
        spans[now].style.color = 'red';
        if (this.run) {
            this.slow = 1;
        } else {
            this.slow = this.slow * 0.995;
        }
        this.deg -= this.slow;
    }
}

在上述代码中,我们通过循环前面生成的所有 span 标签,并给每个 span 标签都添加上相关的样式,最后实现的如下的静态画面:

『 JS真好玩』关于我用原生 JS 实现一个有趣的抽奖程序😁

到这里静态的圆已经通过 JS 动态绘制出来了,但是它还不会动,接下来我们就让它动起来。其实要让整个抽奖程序动起来也很简单,只需要添加一个定时器即可,代码如下:

class Lottery {
    //...other code

    animate() {
        setInterval(() => this.draw(), 10);
    }
}

我们只需要在 init 方法中调用 animate 即可。

到这里,还没完,剩下最后一步,就是何时让这个抽奖程序停下来呢?这里我给 document 添加了一个键盘抬起的事件,通过 addEventListener()document 绑定了一个 keyup 事件,然后监听键盘的 code 是否为空格键,如果是空格键就停止,下面一起来看最后的代码:

class Lottery {
    //...other code

    event() {
        document.addEventListener('keyup',  (e) => {
            if (e.code === 'Space') {
                    this.run = !this.run;
            }
        });
    }
}

event 方法也需要在 init 方法中进行调用,这样当数据初始化好的时候就准备好了需要的内容。

最终的实现效果可以在这里进行查看:

总结

我们仅仅只使用了原生 JS 的几个 API ,就实现了这个抽奖效果。在实际的开发中,虽然我们已经很少用到这些原生的 API 了,但是我们还是需要知道相关的知识点,这样不仅对于我们的开发有帮助,对我们学习新的知识也会有帮助。让我们一起加油吧!

最后,如果这篇文章有帮助到你,❤️关注+点赞❤️鼓励一下作者,谢谢大家

往期回顾

『 实战』从0到1,带你开发开发一款令人惊叹的时钟特效