如何用单词数组实现打字机效果

问题描述 投票:0回答:1

我实现了循环打字机效果;然而,在第一次遍历数组之后,数组中的第一个单词不会再次被输入。另外,我在最后一个单词之后在第二个单词开始之前收到几个“未定义”。我希望它从第一个单词开始。这是我的代码:

const { useEffect } = React;

const words = ["Business", "Company", "Startup"];

let i = 0;
let a = 0;
let txt = `${words[a]}`;
let speed = 1100;
let loop = true;

function Home() {
  const typeWriter = (headerMessage: any) => {
    if (i < txt.length) {
      headerMessage.innerHTML += txt.charAt(i);
      i++;
      setTimeout(() => typeWriter(headerMessage), speed);
    } else if (loop) {
      clearText(headerMessage);
    }
  }

  const clearText = (headerMessage: any) => {
    headerMessage.innerHTML = "";
    i = 0;
    a++;
    txt = `${words[a]}`;
    if (a > 3) {
      a = 0;
    }
    setTimeout(() => {
      typeWriter(headerMessage);
    }, 2000);
  }

  useEffect(() => {
    const headerMessage = document.getElementById("header-message");
    if (headerMessage) {
      typeWriter(headerMessage);
    }

  }, []);
  
  return (
    <main>
      <section>
        <section>
          <div>Let Us Help Grow Your<p id="header-message"></p>.</div>
        </section>
        <section></section>
      </section>
    </main>
  );
}

ReactDOM.createRoot(document.body).render(<Home />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>

javascript reactjs next.js
1个回答
0
投票

我的想法是将

words
转换为
frames

['aa', 'bb']
将会是
['', 'a', 'aa', '', 'b', 'bb']

然后使用间隔计时器将这些帧放入 dom

const { useEffect, useState } = React;

const words = ["Business", "Company", "Startup"];

const TypeEffect = ({ words }) => {
 
  const [typed, setTyped] = useState('');
  
  useEffect(() => {
    const frames = words.map((w) => {
      return Array(w.length + 1).fill('').map((item, idx) => w.slice(0, idx))
    }).flat();
    
    let frameIdx = 0;
    let timer = setInterval(() => {
      setTyped(frames[frameIdx]);
      frameIdx++;
      if (frameIdx === frames.length) { frameIdx = 0; }
    }, 200)
    
   return () => clearInterval(timer);
  
  }, []);

  return (
    <div>{typed}</div>
  )
}

function Home() {
  return (
    <main>
      <section>
        <section>
          <div>Let Us Help Grow Your <TypeEffect words={words}/>.</div>
        </section>
        <section></section>
      </section>
    </main>
  );
}

ReactDOM.createRoot(document.body).render(<Home />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>

© www.soinside.com 2019 - 2024. All rights reserved.