[javasscript] toss a smooth lottery page that is too basic to be basic

Time:2021-12-21

preface

The thing is, as a person with very low willpower, he has been looking for ways to improve his willpower recently.
Then I decided to try the so-called “establishment of reward mechanism”, that is, give myself some rewards after completing a willpower challenge (the specific operation methods are not described here).
Then, a silky “lucky draw page” has naturally joined my (blind) to-do (folding) to-do (Teng) matters.

The whole process is relatively simple, and the knowledge involved is relatively basic. As the first article of this blogtechnologyThe article, plus as a technical Xiaobai, is relatively simple to write. I hope I can give you some help. If you have any suggestions or criticisms, you are welcome to give feedback.

Technology stack / framework involved

  • Front end Development Basics (HTML / CSS / JavaScript)
  • JavaScript ES6 syntax
  • Vue. JS related technical knowledge
  • JavaScript asynchronous knowledge

Basic code

Let’s start with the overall basic code

Lottery
    
        #app {
            margin: auto;
            width: 200px;
            text-align: center;
        }
    



    
        {{item}}
        Start!
    

    


    const app = new Vue({
        el: "#app",
        data: {
            List: ['1 points',' 5 points', '10 points',' 20 points', 'thank you for your patronage', 'do it again'],
            Item: "start the lottery!"
        },
        methods: {
            start() {
                for (let index = 0; index < 50; index++) {
                    setTimeout(() => {
                        this.item = this.list[Math.round(Math.random() * (this.list.length - 1))]
                    }, 100 + index * 100)

                }

            }
        }
    })

You can see that the overall page elements are simple, exceptOutermost div elementIn addition, there is only one left to start the lotteryButtonAnd a to display the current itemParagraph element。 It is referenced through the external chainVue framework

In data,List arrayAs a prize pool, it is used to place items that can be extracted,Item variableIt is used to indicate the currently extracted item and is the same as that used to display the current itemParagraph elementBind inStart methodBefore execution,Item variableThe default value is “start lottery!”.

There is only one methodStart methodUsed to start the lottery. adoptFor loop, 50 times of extraction.setTimeOutThe extraction time is controlled at 100 milliseconds, that is, the extraction is performed every 100 millisecondsList arrayReplace the current value with a random value fromItem variable


The effect is shown in the figure below ⬇️
image

demand

There is no doubt that our existing basic functions are too simple, rigid extraction process, no rigorous extraction rules, etc., which makes our lottery system look likeAnd sunsetThe “win millions of cash” roulette revealed and unspeakable sense of cheapness, so “how to improve” is particularly critical.

  1. Optimize the extraction process to make the extraction process smooth and less rigid
  2. Optimize the extraction rules to make the extraction rules more rigorous
  3. Optimize and improve some details

Perfection process

Optimize extraction process

Since the extraction interval of item is a fixed 100 milliseconds, it looks very stiff and not silky, so optimize the extraction interval to make it look silky and smooth.

  • Update of start method:
async start() {
                for (let index = 0; index < 50; index++) {
                    this.item = await new Promise(resolve => {
                        setTimeout(() => {
                            resolve(this.list[Math.round(Math.random() * (this.list.length - 1))])
                        }, Math.round(this.getTime(index)))
                    })
                }
            },

Set asynchronous functionsetTimeOutconductawaitAsynchronous processing, so that the interval can be superimposed, which is convenient for us to control the interval. Due to the use ofawaitKeyword, so this function addsasyncPrefix. Interval uses the newly added functiongetTimePass parameter acquisition.

  • New gettime method
getTime(index) {
                //Initial / normal interval
                let time = 80
                //Start interval processing
                if (index <= 10) {
                    time = time + (11 - index) * 20
                }
                //End interval processing
                if (index >= 39) {
                    time = time + (index - 39) * 20
                    if (index === 49) time = 1000
                }
                return time
            }

Obtain the number of cycles at that time through the parameter index, and calculate the corresponding interval for this time to return. (it is a simple method, and it is only for this project. It will be encapsulated and improved when you are free. The algorithm of interval time has only been simply calculated by the author, so that it looks more in line with the author’s definition of “smooth”. If you don’t like it, you can try to change it yourself.After all, it’s an experimental project. It’s OK to use it

Optimize extraction rules

Because the extraction rules do not add any restrictions, it is likely that the extracted items are the same as the previous one when the item is extracted, which leads to problems when the item is displayed and switched. It seems that the item is not extracted.

  • Update of start method:
async start() {
                for (let index = 0; index < 50; index++) {
                    this.item = await new Promise(resolve => {
                        setTimeout(() => {
                            resolve(this.getItem())
                        }, Math.round(this.getTime(index)))
                    })
                }
            },

Instead of simply returning the extraction result, it returnsgetItemMethod to add restrictions on the extracted item results.

  • Add getitem method
getItem() {
                let newItem;
                do {
                    newItem = this.list[Math.round(Math.random() * (this.list.length - 1))]
                } while (this.item === newItem);
                return newItem
            }

If the same result as the previous item is extracted, repeat the extraction until different results are extracted.

Optimization details

data: {
            startButtonDisabled: false,
            finished: false,
            List: ['1 points',' 5 points', '10 points',' 20 points', 'thank you for your patronage', 'do it again'],
            Item: "start the lottery!"
        },

staydataAdd instartButtonDisabledandfinishedUsed to record the button status and lottery status respectively.

handleStart(index) {
                if (index === 0) {
                    this.finished = false
                    this.startButtonDisabled = true
                }
            },
            handleEnd(index) {
                if (index === 49) {
                    this.finished = true
                    this.startButtonDisabled = false
                }
            }

Add functionhandleStartandhandleEndyesstartMethod to optimize the details by adding events at the beginning and end of the loop body. When the passed in parameter index is 0 (the beginning of the loop), the method is usedhandleStartChange the lottery status to no lottery, disable the button, and use the method when the incoming parameter is 49 (end of cycle)handleEndChange its state again.

async start() {
                for (let index = 0; index < 50; index++) {
                    this.handleStart(index)
                    this.item = await new Promise(resolve => {
                        setTimeout(() => {
                            resolve(this.getItem())
                        }, Math.round(this.getTime(index)))
                    })
                    this.handleEnd(index)
                }
            },

staystartMethodhandleStartandhandleEndmethod.

{{item}}
        Start!

Modify the page elements so that the corresponding elements will followdataChanges due to the change of data state in.

p.active {
            font-weight: bold;
            color: red
        }

Finally, the lottery status is trueactiveClass to add CSS style, optimization completed!

Final code

Lottery
    
        #app {
            margin: auto;
            width: 200px;
            text-align: center;
        }

        p.active {
            font-weight: bold;
            color: red
        }
    



    
        {{item}}
        Start!
    
    


    const app = new Vue({
        el: "#app",
        data: {
            startButtonDisabled: false,
            finished: false,
            List: ['1 points',' 5 points', '10 points',' 20 points', 'thank you for your patronage', 'do it again'],
            Item: "start the lottery!"
        },
        methods: {
            async start() {
                for (let index = 0; index < 50; index++) {
                    this.handleStart(index)
                    this.item = await new Promise(resolve => {
                        setTimeout(() => {
                            resolve(this.getItem())
                        }, Math.round(this.getTime(index)))
                    })
                    this.handleEnd(index)
                }
            },
            getTime(index) {
                //Initial / normal interval
                let time = 80
                //Start interval processing
                if (index <= 10) {
                    time = time + (11 - index) * 20
                }
                //End interval processing
                if (index >= 39) {
                    time = time + (index - 39) * 20
                    if (index === 49) time = 1000
                }
                return time
            },
            getItem() {
                let newItem;
                do {
                    newItem = this.list[Math.round(Math.random() * (this.list.length - 1))]
                } while (this.item === newItem);
                return newItem
            },
            handleStart(index) {
                if (index === 0) {
                    this.finished = false
                    this.startButtonDisabled = true
                }
            },
            handleEnd(index) {
                if (index === 49) {
                    this.finished = true
                    this.startButtonDisabled = false
                }
            }
        }
    })

The effect is as follows ⬇️
image

epilogue

It’s just a simple front-end example without perfect packaging, so it’s released. I hope it will be helpful to you. In the future, I will try to publish some nutritious technical cases as often as possible. At the same time, I will also record the interesting knowledge (PIT) I encounter in the process of learning and work.

Thank you for reading and wish you a happy life.

Recommended Today

Swift FAQ

1、 Foundation 1. What is the difference between class and struct? a. Struct will automatically generate the required constructor. The constructor with which attribute is not assigned an initial value will be generated with which attribute as the parameter. But class doesn’t. write it yourself struct StructTest { var name:String var age:Int } class ClassTest […]