PK creative Spring Festival, I am participating in the “Spring Festival creative submission contest”, please see: Spring Festival creative submission Contest

preface

Presumably, we often encounter such a question: what to eat today? If the person around you is lovable, responsible and respects you, he or she will say, “Whatever.” Well, the hydrangea is back, since you don’t know what to eat, it’s better to decide randomly!

The content of this article is to implement a very simple random selector – what to eat? It provides advice for those of us who can’t make decisions about what to eat at home during the Spring Festival holiday.

Let’s take a look at the implementation effect. At the end of the article, we posted the experience address.

The specific implementation

It is mainly composed of two parts – dynamic background & random selector

Implementation of background

The background wall is composed of a number of terms that fade in and out, and their positions are random and intermittent. This is done using animation and setInterval. The CSS section will be posted together in the final source code.

  1. First enter alternative foods in the JS code and save them in an array for subsequent random operations.

  1. The occurrence of a noun is essentially inserting a DOM element into the HTML, so we need two functions to generate the required DOM and randomly initialize where it occurs.
function createFood(itemText){
    let p = document.createElement('p')
    let body = document.body
    let { x, y } = randomPos()    // Randomly initialize the position
    p.innerText = itemText
    p.className = 'food-item'
    p.style.left = x + 'px'
    p.style.top = y + 'px'
    p.style.animationDuration = ADD_STEP * MAX_NUM / 1000 + 's'  // Dynamically set the animation duration, which will be covered later
    body.appendChild(p)
}

function randomPos(){
    let x = Math.floor(Math.random() * window.innerWidth)
    let y = Math.floor(Math.random() * window.innerHeight)
    return { x, y }
}
Copy the code
  1. We use timers to add DOM elements intermittently. To prevent the array from crossing bounds, determine whether the current operation index exceeds the array length and reset to 0 if it does.

    Where, ADD_STEP indicates the timer frequency, which I set to 200ms.

let nowIndex = 0
const ADD_STEP = 200

setInterval(() = > {
    if(nowIndex >= foodArr.length)
        nowIndex = 0
    createFood(foodArr[nowIndex])
    nowIndex ++
}, ADD_STEP);
Copy the code
  1. The problem with this is that if we keep adding more and more dom elements to our page, it will pile up. So we need a function to remove the dom that is already present.
function removeFood(){
    let foodElements = document.querySelectorAll('.food-item')
    let body = document.body
    body.removeChild(foodElements[0]) // Remove the top element
}
Copy the code
  1. Here we use setTimeout to delay the removal of elements. We want to take the same amount of time from element generation to fade as it takes to remove it, that is, at the end of the animation of a single element it is removed, so that the total number of elements on the page does not change once it reaches the threshold.

    Therefore, modify the contents of the timer and synchronize the DURATION of the CSS animation.

    Delay time === Animation duration test found that ADD_STEP quotient is exactly the number of final nouns on the page.

const ADD_STEP = 200
const MAX_NUM = 20 // The total number of elements on the page threshold

setInterval(() = > {
    if(nowIndex >= foodArr.length)
        nowIndex = 0
    createFood(foodArr[nowIndex])
    nowIndex ++
    
    // Add delay removal element
    setTimeout(() = > {
        removeFood()
    }, ADD_STEP * MAX_NUM);
}, ADD_STEP);

// As mentioned above
p.style.animationDuration = ADD_STEP * MAX_NUM / 1000 + 's'
Copy the code

Randomly selected implementation

This one is even easier. Listen for button clicks, and if it’s clicked, change the text of the button, and the what to eat column starts scrolling. When the button is clicked again, the button is restored and the scrolling stops to complete the selection process.

btn.addEventListener('click'.() = >{
    let i = 0

    if(! (flag %2)){
        btn.innerText = 'That's it! '
        timer = setInterval(() = > {
            if(i >= foodArr.length)
                i = 0
            foodNameEl.innerText = foodArr[i]
            i ++
        }, 50);
    }else{
        clearInterval(timer)
        btn.innerText = 'Start selecting'
    }
    flag ++
})
Copy the code

Online experience & implementation source code

Experience address stamp here oh

The source code section

<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Nuggets - What to eat for Chinese New Year</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            user-select: none;
        }

        body {
            width: 100vw;
            height: 100vh;
            background-color: #e74c3c;
            position: relative;
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        .food-item {
            font-size: 1.5 rem;
            color: #f1c40f;
            white-space: nowrap;
            position: absolute;
            animation: hideFood linear forwards;
            cursor: pointer;
        }

        @keyframes hideFood {
            from {
                opacity: 1;
                transform: scale(1.5);
                filter: blur(2px);
            }

            20% {
                filter: blur(0);
            }

            to {
                opacity: 0;
                transform: scale(0); }}main {
            background-color: #e74c3c;
            text-align: center;
            position: relative;
            z-index: 1;
        }

        .content {
            font-size: 2rem;
            font-weight: bold;
            color: #f1c40f;
            text-shadow: 0px 0px 3px # 333;
        }

        .food-name {
            color: #ecf0f1;
        }

        .btn {
            margin: 1.2 rem 0;
            padding:.8rem 3rem;
            font-size: 1.2 rem;
            font-weight: normal;
            display: inline-block;
            background-color: #f39c12;
            color: #ecf0f1;
            border-radius: 5px;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <main>
        <div class="content">
            <span>I will eat during the Spring Festival holiday</span>
            <span class="food-name">What?</span>
        </div>
        <span class="btn">Begin to choose</span>
    </main>

    <script>
        let foodArr = ['jiaozi'.'hot pot'.'meat'.'barbecue'.'Fried rice'.'meter'.'chicken'.'hamburger'.'Malatang'.'Dough bumps'.'Marinated pork rice'.'liangpi'.'dumplings'.'fish'.'fruit'.'Lean meatballs'.'Noodles with soy sauce'.'Multigrain pancakes'.'take food'.'pizza'.KFC.'Little Wonton'.'Rou jia mo'.'Spicy spicy Pot'.'Green salad'.'Three Saucepan'.'Braised Chicken with rice'.'Sheng Jian Bao'.'Pickled cabbage fish'.'soil']
        let nowIndex = 0
        let flag = 0
        let btn = document.querySelector('.btn')
        let foodNameEl = document.querySelector('.food-name')
        const ADD_STEP = 200
        const MAX_NUM = 20

        function createFood(itemText){
            let p = document.createElement('p')
            let body = document.body
            let { x, y } = randomPos()
            p.innerText = itemText
            p.className = 'food-item'
            p.style.left = x + 'px'
            p.style.top = y + 'px'
            p.style.animationDuration = ADD_STEP * MAX_NUM / 1000 + 's'
            body.appendChild(p)
        }

        function removeFood(){
            let foodElements = document.querySelectorAll('.food-item')
            let body = document.body
            body.removeChild(foodElements[0])}function randomPos(){
            let x = Math.floor(Math.random() * window.innerWidth)
            let y = Math.floor(Math.random() * window.innerHeight)
            return { x, y }
        }

        setInterval(() = > {
            if(nowIndex >= foodArr.length)
                nowIndex = 0
            createFood(foodArr[nowIndex])
            nowIndex ++
            setTimeout(() = > {
                removeFood()
            }, ADD_STEP * MAX_NUM);
        }, ADD_STEP);

        btn.addEventListener('click'.() = >{
            let i = 0

            if(! (flag %2)){
                btn.innerText = 'That's it! '
                timer = setInterval(() = > {
                    if(i >= foodArr.length)
                        i = 0
                    foodNameEl.innerText = foodArr[i]
                    i ++
                }, 50);
            }else{
                clearInterval(timer)
                btn.innerText = 'Start selecting'
            }
            flag ++
        })
    </script>
</body>
</html>
Copy the code

conclusion

A few simple lines of code that more or less solves the problem of not knowing what to eat hahaha.

Need friends to modify the code in the foodArr array part, according to their own taste custom!

I wish everyone a happy New Year 💖!