簡體   English   中英

React 中的打字機效果

[英]Typewriter effect in React

我正在嘗試在 React 組件中制作打字效果。 我傳入一個字符串數組,並嘗試在一段時間后逐個字符地呈現它們(使用 setTimeout)。 這是我的代碼

  state = {
    typeColor: {
      color: "blue"
    },
    typed: ""
  };

  componentDidMount() {
    this.props.typewriter.map(string => {
      console.log("1", string);
      return this.stringChecker(string);
    });
  }

  typeWriter(string) {
    if (string.length === 0) {
      return;
    }
    console.log("3", string);
    this.setState((state, props) => ({ typed: state.typed.concat(string[0]) }));
    console.log(this.state.typed);

    setTimeout(() => this.typeWriter(string.slice(1)), 120);
  }
  stringChecker(string) {
    console.log("2", string);
    if (string === "Qurram") {
      this.setState({ typeColor: { color: "blue" } });
    } else {
      this.setState({ typeColor: { color: "pink" } });
    }
    this.typeWriter(string);
  }

  render() {
    return <div style={this.state.typeColor}>{this.state.typed}</div>;
  }
}

現在我期待它的執行流程是這樣的:在映射函數中“選擇”字符串數組的第一個元素 -> 我為第一個元素調用 stringchecker -> 我為第一個元素調用打字機,並迭代人物。 然后我回到地圖功能並為下一步做同樣的事情。 似乎流程根本不是這樣,而是在每個字符切片的兩個字符串之間交替。 如果有人能向我解釋這一點,我將不勝感激。 非常感謝

沙盒鏈接: https : //codesandbox.io/s/morning-dust-18nq5

您可以簡單地使用useEffect()鈎子,它會在每次重新渲染(隨機延遲)后增加文本的可見部分(存儲在組件的狀態中),直到整個文本消失。

您可以在下面找到此概念的現場演示:

 const { useState, useEffect } = React, { render } = ReactDOM const srcString = `That's the text I'm going to print out` const Typewriter = ({srcString}) => { const [{content,carriage}, setContent] = useState({content:'',carriage:0}) useEffect(() => { if(carriage == srcString.length) return const delay = setTimeout(() => { setContent({content:content+srcString[carriage], carriage: carriage+1}) clearTimeout(delay) }, 0|(Math.random()*200+50)) }, [content]) return <span>{content}<span className="cursor">|</span></span> } render ( <Typewriter {...{srcString}} />, document.getElementById('root') )
 .cursor{animation:1s blink step-end infinite}@keyframes blink{from,to{color:transparent}50%{color:#000}}@-moz-keyframes blink{from,to{color:transparent}50%{color:#000}}@-webkit-keyframes blink{from,to{color:transparent}50%{color:#000}}@-ms-keyframes blink{from,to{color:transparent}50%{color:#000}}@-o-keyframes blink{from,to{color:transparent}50%{color:#000}}
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><div id="root"></div>

輸入邏輯很好,但是請注意 setTimeout 是異步的,因此它不會等待輸入整個單詞后再切換到下一個單詞。 解決方案是使整個打字流程異步,這樣您就不會在輸入前一個單詞之前切換到下一個單詞。

這是沙盒演示: https : //codesandbox.io/s/boring-greider-824nd

主要的變化是這個:

if (string.length === 0) {
  words = words.slice(1);
  words[0] && this.typeWord(words[0], words);
}

檢查我們是否完成了一個單詞的輸入,然后將其切片,以獲得下一個單詞。 如果我們還有單詞,我們用應該輸入的單詞和接下來應該輸入的單詞數組調用typeWord 如果沒有剩下的話,我們退出打字。

是的, setTimeout()在處理需要同步執行的任務時可能會很棘手(比如打字效果)。

這是使用async/await的另一種方法。 我將typeWriter方法typeWriter異步,因此它只會在輸入字符串中的所有字符后才返回。 之后,將允許鍵入 NEXT 字符串。 為此, stringChecker還需要異步。 檢查一下,讓我知道是否有任何令人困惑的地方。

https://codesandbox.io/s/youthful-davinci-d5bk5?fontsize=14&hidenavigation=1&theme=dark

另外……如果你只是想讓它運行起來,我做了一個 TypeIt,一個 JS 打字庫,還有一個 React 組件版本。 如果有用,請查看:

https://github.com/alexmacarthur/typeit-react

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM