preface

After implementing Pikachu with CSS, I began to wonder if there was a way to dynamically implement Pikachu. With this idea in mind, I began to check relevant materials and blogs, and found that there were quite a few, so I realized dynamic Pikachu through their code and my own understanding. Preview image below

Implement dynamic Pikachu

Before we start, we need to think about how to display the page dynamically. Using setInterval built into JS can solve this problem.

For example when we have a div in HTML we can do something like this.

<div id="demo"></div>
Copy the code

In JS, you can add up

let n = 1;
const demo = document.querySelector('#demo')
demo.innerHTML = n;
setInterval((a)= >{   
    n+=1;
    demo.innerHTML=n;
},1000)
Copy the code

So it’s going to show up on the page that every second n is going to +1, and since numbers can do that then strings can do that too, all we need to do is replace let n = 1 with let n = “hello world”, The thing to notice at this point is that in JS we’re no longer rendering “Hello World” itself, we’re rendering its substrings, which is what the code shows.

let n = 1;
const string = "hello world";
const demo = document.querySelector('#demo');
demo.innerHTML = string.substr(0,n);
setInterval((a)= >{
    n+=1;
    demo.innerHTML=string.substr(0,n);
},1000)
Copy the code

One thing to note is that at run time the above code looks fine, but it is actually buggy. The bug is that after the string is printed, the output of n does not stop, but continues to accumulate. How to fix this bug? It’s very simple and we just need to determine whether the sum of n is greater than the length of the string.

const string = "hello world";
let n = 1;
const demo = document.querySelector('#demo');
demo.innerHTML = string.substr(0,n);
let id = setInterval((a)= >{
    n+=1;
    if(n>string.length){
        window.cleanInterval(id);
        return;
    }
    demo.innerHTML=string.substr(0,n);
},1000)
Copy the code

Once we’ve solved this problem we can just plug in the HTML structure of pikachu. So here we need two divs one for HTML and one for text, and that’s what it looks like in code.

<div id="demo"></div>
<div id="demo2"></div>
<div id="html">
    <div class="skin">
        <div class="eye left"></div>
        <div class="eye right"></div>
        <div class="nose">
            <div class="yuan"></div>
        </div>
        <div class="mouth ">
            <div class="up">
                <div class="lip left"></div>
                <div class="lip right"></div>
            </div>
            <div class="down">
                <div class="yuan1">
                    <div class="yuan2"></div>
                </div>
            </div>
        </div>
        <div class="mouth "></div>
        <div class="face left">
        </div>
        <div class="face right">
        </div>
    </div>
</div>
Copy the code
const string = `  `;
let n = 1;
const demo = document.querySelector('#demo');
const demo2 = document.querySelector('#demo1');
demo.innerText = string.substr(0,n);
demo2.innerHTML = string.substr(0,n);
let id = setInterval((a)= >{
    n+=1;
    if(n>string.length){
        window.cleanInterval(id);
        return;
    }
    demo.innerText=string.substr(0,n);
    demo2.innerHTML = string.substr(0,n);
},1000)
Copy the code

We’re done here. We just need to change the CSS in string to the pikachu CSS. Or import it using ES6 syntax.

A problem with this is that when the page is previewed, the pikachu implementation is at the bottom of the page instead of in a fixed location. At this point, we need to fix the id of the HTML location can be.

#html {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 50vh;
}
Copy the code

After this problem is solved, a new problem arises, the HTML is fixed, but the code does not scroll when it is previewed on a web page. Since the code is written in demo and Demo2, demo2 is a page structure, so just hide it, make an absolute position in the demo, and let the code scroll.

#demo2 {
  display: none;
}

#demo {
  position: fixed;
  height: 50vh;
  top: 0;
  left: 0;
  width: 100%;
  border: 1px solid red;
  overflow: scroll;
}
Copy the code

But if I write it this way, I don’t know when to pull the scroll bar. A very rude way to write it is to pull the top of the scrollbar all the way to the bottom or demo.scrollHeight, which means we can pull as high as the scrollbar can go.

demo.innerText=string.substr(0,n);
demo2.innerHTML = string.substr(0,n);
demo.scrollTop = 99999999/demo.scrollHeiht; 
Copy the code

Since the scrollbar page is a little ugly, I chose to hide the scrollbar. This is the perfect way to hide the scroll bar while also pulling it.

#demo {
  overflow-y: auto;
}
#demo::-webkit-scrollbar {
  display: none;
}
Copy the code

If you think the “style” tag looks ugly in the preview, we can do this by changing the demo2 tag that controls the page structure from div to “style”. Then you don’t need style anywhere in the JS string.

<style id="demo2"></style>
<div id="demo"></div>
Copy the code

Add features to Pikachu

Now I’m going to give Pikachu what I thought it would be Play, pause, slow, medium and Fast.

<div id="buttons">
    <button id="btnPause">suspended</button>
    <button id="btnPlay">play</button>
    <button id="btnSlow">slow</button>
    <button id="btnNormal">Medium speed</button>
    <button id="btnFast">fast</button>
</div>
Copy the code

So once we’ve done that, we’re going to add CSS, and since HTML is a fixed position, we’re going to need to fix the position of buttos to display it.

#buttons {
  position: fixed;
  right: 0;
  top: 0;
  z-index: 10;
  display: flex;
  flex-direction: column;
  margin-top: 10px;
  margin-right: 10px;
}
#buttons>button {
  margin-bottom: 10px;
  padding: 4px 8px;
}
Copy the code

Once we’re done, we’ll notice that when we preview, the button suddenly gets bigger. Why is that? This is because dynamically added styles affect the outside styles. Then we need to change the code for adding styles dynamically

.skin* {box-sizing:border-box;margin:0;padding:0}
.skin *::before.skin *::after{box-sizing:border-box}

.skin {
    position:relative;
    height:50vh
    background-color: #ffe600;
}
Copy the code

Add CSS to the outer layer

* {box-sizing:border-box;margin:0;padding:0}
 *::before, *::after{box-sizing:border-box}
Copy the code

This way you can add button functionality.

suspended

Let’s implement a pause function, the idea is very simple, when I click on the time to smash an alarm clock.

const btnPause = document.quertSelector('#btnPause');
btnPause.onclick = () = {
    window.cleanInterval(id);
}
Copy the code

play

Play function is also relatively simple, click play, we can create a new alarm clock.

const run = (a)= >{
    n+=1;
    if(n>string.length){
        window.clearInterval(id);
        return}} omit the codelet id = setInterval((a)= >{
    run();
})
const btnPlay = document.querySelector('#btnPlay');
btnPlay.onclick = (a)= >{
    id = setInterval((a)= >{
        run()
    },0)}Copy the code

Medium, fast, slow

These three functions are actually the same, the difference is the speed difference. The idea is also similar to implementing pause and play will not be repeated.

Omit codelet time = 100 // Set the speed timeOmit codeconst btnSlow = document.querySelector('#btnSlow');
btnSlow.onclick = () = >{
    window.cleanInterval(id);
    time = 300;
    id = setInterval((a)= >{
        run();
    },time)
}

const btnNormal = document.querySelector('#btnNormal');
btnNormal.onclick = () = >{
    window.cleanInterval(id);
    time = 100;
    id = setInterval((a)= >{
        run();
    },time)
}

const btnFast = document.querySelector('#btnFast');
btnFast.onclick = () = >{
    window.cleanInterval(id);
    time = 0;
    id = setInterval((a)= >{
        run();
    },time)
}

Copy the code

So far we have achieved dynamic display of Pikachu.

Project source code project preview