【问题标题】:typing animation on each element with its class在每个元素及其类上键入动画
【发布时间】:2022-01-04 02:19:01
【问题描述】:

我正在尝试制作打字动画,但它不起作用,我不知道为什么。我知道我可以在 CSS 中做到这一点,但我想在 JS 中尝试一下。问题可能出在函数本身我不是 JS 中最好的。

<p class="typing-animation">this will be animated</p>
<p class="typing-animation">this aswell</p>
<script>
const sleep = (ms) => {
  return new Promise((resolve) => setTimeout(resolve, ms));
};

const toType = document.getElementsByClassName("typing-animation");

document.getElementsByClassName("typing-animation").textContent = "";

(async (toType) => {
  for (let each of toType) {
    text = each.textContent;
    each.textContent = "";
    let i = 0;
    for (let every of text) {
      every.textContent += text[i];
      await sleep(200);
      i++;
    }
  }
})(toType);
</script>

【问题讨论】:

    标签: javascript animation


    【解决方案1】:

    我想这就是你所追求的?

    <p class="typing-animation">this will be animated</p>
    <p class="typing-animation">this aswell</p>
    
    <script>
    const sleep = (ms) => {
      return new Promise((resolve) => setTimeout(resolve, ms));
    };
    
    // This is an array of html elements, since getElementsByClassName returns an array, since there can be more than one html element with that class.
    const elements = document.getElementsByClassName("typing-animation");
    
    (async (typedElements) => {
       let texts = []
       
       for (let element of typedElements){
        // The property to access the text inside the elements .innerHTML, if its a user interactuable element such as <input> or <textarea> then its .value
        texts.push(element.innerHTML);
        element.innerHTML = "";
       }
       
       // texts and typedElements has the same length.
       for (let i = 0; i < texts.length; i++) {
          for (let character of texts[i]) {
            typedElements[i].innerHTML += character;
            await sleep(200)
          } 
       }
      
    })(elements);
    </script>

    如果您希望在多个地方实现这种效果,并且更容易实现,那么已经有一个库可以做到这一点,更容易定制和使用:Typed.js

    <span class="typed"></span>
    
    <script src="https://cdn.jsdelivr.net/npm/typed.js@2.0.12"></script>
    
    <script>
      // For more examples check: https://github.com/mattboldt/typed.js
      // Full docs at: https://mattboldt.github.io/typed.js/docs/
      const options = {
        strings: ['This will be typed!', 'This too! ^500 <br> And this will go under!'],
        typeSpeed: 40,
        backSpeed: 40,
        backDelay: 2000,
      };
      
      // We'll bind the typing animation to the .typed class.
      let typed = new Typed('.typed', options);
    </script>

    【讨论】:

    • 我很想使用 typed.js,但我试图让我的项目仅限前端。感谢您的建议
    • 它是一个前端库,使用该库的示例再次查看回复!
    【解决方案2】:

    你走在正确的道路上。为了便于阅读,我刚刚整理了一些内容。

    这是它的代码框:https://codesandbox.io/s/typing-animation-kdn8v

    我假设您希望动画并行发生。出于这个原因,我们希望遍历每个 HTML 元素并在每个元素上调用我们的 animateType 函数,而无需等待。

    animateType 的每次调用都意味着此 HTML 元素的此函数的副本正在运行。这样,函数内部的变量text 就不会在 HTML 元素中混淆。这称为“关闭”。函数“实例”内的所有变量,仅存在于该函数实例内。

    我们存储原始文本,然后清除 HTML 元素的内容,然后像您一样循环缓存文本的字母,并将每个字母添加到 HTML 元素中。

    // Stackoverflow: https://stackoverflow.com/questions/70573442/typing-animation-on-each-element-with-its-class
    
    const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
    
    const clearAndCache = (elements) => {
      let cachedText = [];
      for (let element of elements) {
        cachedText.push(element.textContent);
        element.textContent = "";
      }
      return cachedText;
    };
    
    const animateTypeSync = async (typeables, ms) => {
      const cachedText = clearAndCache(typeables);
    
      for (let i = 0; i < typeables.length; i++) {
        for (let character of cachedText[i]) {
          typeables[i].textContent += character;
          await sleep(ms);
        }
      }
    };
    
    const animateTypeAsync = (typeables, ms) => {
      const cachedText = clearAndCache(typeables);
    
      Array.from(typeables).forEach(async (element, i) => {
        for (let character of cachedText[i]) {
          element.textContent += character;
          await sleep(ms);
        }
      });
    };
    
    const elementsSync = document.getElementsByClassName("typing-animation-sync");
    animateTypeSync(elementsSync, 200);
    
    const elementsAsync = document.getElementsByClassName("typing-animation");
    animateTypeAsync(elementsAsync, 150);
    <!DOCTYPE html>
    <html>
      <head>
    <title>Typing Animation</title>
    <meta charset="UTF-8" />
      </head>
    
      <body>
    <h1>Typing Animations</h1>
    
    <div style="width: 100%; display: inline-flex;">
      <div style="width: 50%;">
        <h2>Async</h2>
        <p class="typing-animation">These will run</p>
        <p class="typing-animation">at the same time</p>
      </div>
    
      <div style="width: 50%;">
        <h2>Sync</h2>
        <p class="typing-animation-sync">These will animate</p>
        <p class="typing-animation-sync">one at a time</p>
      </div>
    </div>
      </body>
      <script src="src/index.js"></script>
    </html>

    编辑:在 OP 评论后向代码添加了同步版本。

    【讨论】:

    • 我实际上并不想并行运行它,不过感谢您的深入回答
    • @Shiba 不用担心!我已经为你的例子添加了同步版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-05
    • 1970-01-01
    • 2019-04-29
    • 1970-01-01
    • 2017-12-09
    • 1970-01-01
    相关资源
    最近更新 更多