likes
comments
collection
share

关于我Blog首页打字机效果

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

关于我Blog首页打字机效果

如何实现首页打字机效果 我的blog:onecupof.cn

一、 用到的技术

  • JavaScript

  • CSS3=>animation (核心)

  • Vue

二、实现思路

基础实现思想 B 站有小教程我就不赘述了,主要讲讲怎么在博客中应用。

bilibili:【CSS】打字特效(opens new window)

三、在博客系统中应用

你需要知道的是在 VuePress 中,所有在 .vuepress/components 中找到的 *.vue 文件将会自动地被注册为全局的异步组件,如:

.
└─ .vuepress
   └─ components
      ├─ demo-1.vue
      ├─ OtherComponent.vue
      └─ Foo
         └─ Bar.vue
 
        Copied!
    

你可以直接使用这些组件在任意的 Markdown 文件中(组件名是通过文件名提取到的):

<demo-1/>
<OtherComponent/>
<Foo-Bar/>
 
        Copied!
    

于是我们在 components 目录下新建一个 NewFont.vue 文件,并填入以下代码:

TemplateScriptStyle

<template>
  <div></div>
</template> 
        Copied!
    

接下来在你的首页文件 README.md 文件中应用即可。

// ...
​
<NewFont />
 
        Copied!
    

我的目录结构如下: 关于我Blog首页打字机效果

四、普通版本(.html)

<!DOCTYPE html>
<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>Document</title>
    <style>
      :root {
        font-size: 20px;
      }
​
      body {
        display: flex;
        justify-content: center;
        align-items: center;
        min-height: 100vh;
      }
​
      h1 {
        margin: 0;
        padding: 0;
        /* 必须是等宽字体 */
        font-family: monospace;
        /* 由于是等宽字体,1ch 等于 任何数字、英文、符号的宽度 */
        /* width: 1ch; */
        position: relative;
        /* overflow: hidden; */
        /* animation: 1s typing forwards steps(13); */
      }
​
      h1::after {
        content: "";
        display: inline;
        position: absolute;
        width: 5px;
        height: 2ch;
        background-color: #000;
        border-radius: 2px;
        right: -0.5ch;
      }
​
      h1.ended::after {
        animation: 1.1s cursor steps(2, jump-none) infinite;
      }
​
      h1 span {
        --delay: 10s;
        display: inline-block;
        overflow: hidden;
        width: 0ch;
        animation: 0.1s text-in ease-in-out forwards;
        /* animation: 0.1s text-out ease-in-out forwards; */
        animation-delay: var(--delay);
      }
​
      @keyframes text-in {
        from {
          width: 0ch;
        }
​
        to {
          width: 2ch;
        }
      }
​
      @keyframes text-out {
        from {
          width: 2ch;
        }
​
        to {
          width: 0ch;
        }
      }
​
      @keyframes cursor {
        from {
          opacity: 0;
        }
​
        to {
          opacity: 1;
        }
      }
    </style>
  </head>
​
  <body>
    <script>
      let strs = [
        {
          title: "没有梦想,和咸鱼有什么区别",
          stop: 5,
        },
        {
          title: "没有什么能够顾阻你,前进的步伐",
          stop: 10,
          // stop: [4, 13]
        },
      ];
      // 当前进行到第几行
      let currentIndex = 0;
      let h1 = null;
      let spans = null;
​
      setTimeout(() => {
        h1 = document.createElement("h1");
        document.body.appendChild(h1);
​
        init();
      }, 2000);
​
      function init() {
        if (currentIndex == strs.length) {
          currentIndex = 0;
        }
        h1.innerHTML = strs[currentIndex].title;
        h1.innerHTML = h1.textContent.replace(/\S/g, "<span>$&</span>");
​
        let delay = 0;
        spans = [...document.querySelectorAll("span")];
        spans.forEach((span, i) => {
          delay += 0.1;
          if (strs[currentIndex].stop instanceof Array) {
            if (strs[currentIndex].stop.includes(i)) {
              delay += 0.3;
            }
          } else {
            if (strs[currentIndex].stop == i) {
              delay += 0.3;
            }
          }
​
          span.style.setProperty("--delay", `${delay}s`);
        });
​
        h1.addEventListener("animationend", lastEnd);
      }
​
      function lastEnd(e) {
        if (e.target == document.querySelector("h1 span:last-child")) {
          h1.classList.add("ended");
          setTimeout(() => {
            h1.removeEventListener("animationend", lastEnd);
            let delay = 0;
​
            spans.reverse().forEach((span, i) => {
              h1.classList.remove("ended");
              span.style.width = "2ch";
              span.style.animation = "0.1s text-out ease-in-out forwards";
              delay += 0.05;
              // 回去停顿功能
              // if (strs[currentIndex].stop instanceof Array) {
              //   if (strs[currentIndex].stop.includes(spans.length - i)) {
              //     delay += 0.3
              //   }
              // } else {
              //   if (strs[currentIndex].stop == spans.length - i) {
              //     delay += 0.3
              //   }
              // }
              span.style.animationDelay = `${delay}s`;
            });
            h1.addEventListener("animationend", firstEnd);
          }, 2000);
        }
      }
​
      function firstEnd(e) {
        if (e.target == document.querySelector("h1 span:first-child")) {
          spans.forEach((item) => {
            item.remove();
          });
          h1.removeEventListener("animationend", firstEnd);
          currentIndex++;
          // h1.classList.add('ended')
          // h1.classList.remove('ended')
          init();
        }
      }
    </script>
  </body>
</html>
 
        Copied!
    

五、效果

关于我Blog首页打字机效果