[英]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 -> 我為第一個元素調用打字機,並迭代人物。 然后我回到地圖功能並為下一步做同樣的事情。 似乎流程根本不是這樣,而是在每個字符切片的兩個字符串之間交替。 如果有人能向我解釋這一點,我將不勝感激。 非常感謝
您可以簡單地使用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 組件版本。 如果有用,請查看:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.