Just to make a quick note of the idea, there’s a lot of room for improvement

Draw nose (a fan)

Use transparent to draw appropriate triangles

.nose {
  position: absolute;
  border: 10px solid black;
  border-color: black transparent transparent;
  border-bottom: none;
  left: 50%;
  top: 145px;
  margin-left: -10px;
}
Copy the code

Then draw the semicircles on top of the triangle to form the sector

.yuan {
  position: absolute;
  height: 8px;
  width: 20px;
  top: -18px;
  left: -10px;
  border-radius: 8px 8px 0 0;
  background-color: black;
}
Copy the code

Draw two black eyes on the left and right

.eye {
  position: absolute;
  border: 2px solid #000000;
  width: 64px;
  height: 64px;
  left: 50%;
  top: 100px;
  margin-left: -32px;
  border-radius: 50%;
  background-color: #2e2e2e;
}
.eye.left {
  transform: translateX(-118px);
}
.eye.right {
  transform: translateX(118px);
}
Copy the code

Draw the white eye inside the black eye

.eye::after {
  content: "";
  display: block;
  position: absolute;
  border: 2px solid black;
  background: #ffffff;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  left: 10px;
}
Copy the code

Painted lips

Make the left lip

.mouth .up .lip.left {
  border: 3px solid black;
  width: 86px;
  height: 24px;
  border-radius: 0 0 0 50px;
  border-top-color: transparent;
  border-right-color: transparent;
  position: relative;
  transform: rotate(-15deg);
  position: absolute;
  left: 50%;
  margin-left: -50%;
}
Copy the code

Then cover the black vertical line below your nose with a false element

.mouth .up .lip.left::before {
  content: "";
  display: block;
  width: 5px;
  height: 30px;
  position: absolute;
  right: -4px;
  bottom: 0px;
  background-color: #ffdb00;
}
Copy the code

Same principle for making the right lip

.mouth .up .lip.right {
  border: 3px solid black;
  width: 86px;
  height: 24px;
  border-radius: 0 0 50px 0;
  border-top-color: transparent;
  border-left-color: transparent;
  position: relative;
  transform: rotate(15deg);
  position: absolute;
  right: 50%;
  margin-right: -50%;
}
Copy the code
.mouth .up .lip.right::before {
  content: "";
  display: block;
  width: 5px;
  height: 30px;
  position: absolute;
  left: -4px;
  bottom: 0px;
  background-color: #ffdb00;
}
Copy the code

Make your lower lip

.mouth .down {
  border: 1px solid red;
  height: 166px;
  width: 100%;
  position: relative;
  overflow: hidden;
}

.mouth .down .yuan1 {
  border: 1px solid black;
  position: absolute;
  width: 124px;
  height: 1000px;
  left: 50%;
  margin-left: -62px;
  bottom: 0;
  border-radius: 85px/280px;
  background: #9b000a;
}
Copy the code

Then add the same background as the body to the.mouth.up. lip and draw the inside part and the red cheeks

.mouth .down .yuan1 .yuan2 {
  border: 1px solid red;
  position: absolute;
  width: 150px;
  height: 300px;
  background: #fa595b;
  left: 50%;
  margin-left: -75px;
  bottom: -165px;
  border-radius: 100px;
}

.face {
  border: 3px solid black;
  position: absolute;
  width: 88px;
  height: 88px;
  left: 50%;
  margin-left: -44px;
  top: 210px;
}
.face.left {
  transform: translateX(-166px);
  border-radius: 50%;
  background: #ff0000;
}
.face.right {
  transform: translateX(166px);
  border-radius: 50%;
  background: #ff0000;
}
Copy the code

Add animation effects

Animate your nose

@keyframes wave {
  0% {
    transform: rotate(0);
  }
  33% {
    transform: rotate(6deg);
  }
  66% {
    transform: rotate(-6deg);
  }
  100% {
    transform: rotate(0);
  }
}
.nose:hover {
  transform-origin: center bottom;
  animation: wave 220ms infinite linear;
}
Copy the code

Dynamic display

Make a number automatically keep incrementing by 1

  • Create a newtest.htmltest.js
  • Write a div with the id demo in test.html
let n = 1;
demo.innerHTML = n;
setInterval(() => {
  n += 1;
  demo.innerHTML = n;
}, 1000);
Copy the code

The following can write a paragraph, one word one word appear

Const string = "Hello, I'm your old friend "; let n = 1; demo.innerHTML = string.substr(0, n); setInterval(() => { n += 1; demo.innerHTML = string.substr(0, n); }, 300);Copy the code

But there is still a bug in the above code. When you type n, you will find that n keeps increasing after the word is displayed. We just need to cancel the timer after the word is displayed

Const string = "Hello, I'm your old friend "; let n = 1; demo.innerHTML = string.substr(0, n); let id = setInterval(() => { n += 1; if (n > string.length) { window.clearInterval(id); return; } demo.innerHTML = string.substr(0, n); }, 300);Copy the code

Now that we know how to display one word at a time, let’s show our CSS.

Prepare two divs in test.html, one to write CSS tags and one to display CSS content on the page.

However, there is still a problem after this, the display animation is covered by the text. As is shown in

Add the following code to test.html

<style>
  #html {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 50vh;
  }
</style>
Copy the code

We solved the problem of how to make the animation, and then the code can’t see the problem, how to make the scroll bar automatically scroll down, and the animation is not moving

HTML content does not need to be seen by the user and can be hidden

<style>
  #demo2 {
    display: none;
  }
  #demo{
    position: fixed;
    height: 50vh;
    top: 0;
    left: 0;
    width: 100%;
    overflow-y: auto;
  }
  #html {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 50vh;
  }
</style>
Copy the code

Update the code in test.js to make the scroll bar scroll down automatically

let id = setInterval(() => { n += 1; if (n > string.length) { window.clearInterval(id); return; } demo.innerText = string.substr(0, n); demo2.innerHTML = string.substr(0, n); demo.scrollTop = demo.scrollHeight; }, 0);Copy the code

After the scroll bar is hidden, users can still scroll through content

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

Realize slow speed, medium speed, fast playback functions

  1. Add play, pause, slow, medium and fast buttons
  2. The CSS reset affects the button and updates the code in test and JS

Divide the pattern into two pieces that do not affect each other

.skin * {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
.skin *::before,
*::after {
  box-sizing: border-box;
}
.skin {
  background: #ffdb00;
  min-height: 50vh;
  position: relative;
}
Copy the code

3. The train of thought

  • Pause: Clear timer (alarm clock)
  • Play: Run a timer
  • Slow: Smash the alarm clock and reset it to make the time slower

Code optimization

btnSlow.onclick = () => { window.clearInterval(id); time = 300; id = setInterval(() => { run(); }, time); }; // equivalent to btnslow.onclick = () => {window.clearInterval(id); time = 300; id = setInterval(run, time); };Copy the code

The complete optimization is as follows

Pause; btnPause.onclick = () => { window.clearInterval(id); }; Play; btnPlay.onclick = () => { id = setInterval(() => { run(); }, time); }; Slow; btnSlow.onclick = () => { window.clearInterval(id); time = 300; id = setInterval(() => { run(); }, time); }; Medium speed; btnNormal.onclick = () => { window.clearInterval(id); time = 50; id = setInterval(() => { run(); }, time); }; Fast; btnFast.onclick = () => { window.clearInterval(id); time = 0; id = setInterval(() => { run(); }, time); };Copy the code

The optimization result of the preceding code is as follows ↓↓↓

const run = () => { n += 1; if (n > string.length) { window.clearInterval(id); return; } demo.innerText = string.substr(0, n); demo2.innerHTML = string.substr(0, n); demo.scrollTop = demo.scrollHeight; }; const play = () => { return setInterval(run, time); }; let id = play(); const pause = () => { window.clearInterval(id); }; // pause btnpause.onclick = () => {pause(); }; // play btnPlay.onclick = () => {id = play(); }; // btnslow.onclick = () => {pause(); time = 300; id = play(); }; // btnnormal. onclick = () => {pause(); time = 50; id = play(); }; // fast btnfast. onclick = () => {pause(); time = 0; id = play(); };Copy the code

If a function does nothing but call another function, then the outside function can be omitted, right

For example,

btnSlow.onclick = () => { slow(); }; // equivalent btnSlow. Onclick = slow;Copy the code

Block several functions together for one object

const play = () => {
  return setInterval(run, time);
};

let id = play();

const pause = () => {
  window.clearInterval(id);
};

const slow = () => {
  pause();
  time = 300;
  id = play();
};

const normal = () => {
  pause();
  time = 50;
  id = play();
};
const fast = () => {
  pause();
  time = 0;
  id = play();
};
Copy the code
const player = { run: () => { n += 1; if (n > string.length) { window.clearInterval(id); return; } demo.innerText = string.substr(0, n); demo2.innerHTML = string.substr(0, n); demo.scrollTop = demo.scrollHeight; }, play: () => { return setInterval(player.run, time); }, pause: () => { window.clearInterval(id); }, slow: () => { player.pause(); time = 300; id = player.play(); }, normal: () => { player.pause(); time = 50; id = player.play(); }, fast: () => { player.pause(); time = 0; id = player.play(); }};Copy the code

.

bindEvents: () => { document.querySelector("#btnPause").onclick = player.pause; document.querySelector("#btnPlay").onclick = player.play; document.querySelector("#btnSlow").onclick = player.slow; document.querySelector("#btnNormal").onclick = player.normal; document.querySelector("#btnFast").onclick = player.fast; } / /Copy the code

modular

Take a bunch of code and put it in a file and export it, import it