中文字幕一区二区人妻电影,亚洲av无码一区二区乱子伦as ,亚洲精品无码永久在线观看,亚洲成aⅴ人片久青草影院按摩,亚洲黑人巨大videos

光標(biāo)仿真器

發(fā)布于:2021-02-04 14:40:20

0

80

0

react javascript 初學(xué)者 前端

那么我們今天要?jiǎng)?chuàng)建什么呢?

我們將在這個(gè)項(xiàng)目中使用React來模擬用戶輸入效果。

我們的最終輸出將如下所示:

  

項(xiàng)目大綱:

  • 組件將描述的數(shù)組作為輸入。

  • 組件將有一個(gè)閃爍的文本光標(biāo)(“|”)。

  • 文本開始以指定的延遲出現(xiàn)在屏幕中。

  • 光標(biāo)隨著文本類型移動(dòng)。

  • 光標(biāo)在句末閃爍一段時(shí)間。

  • 最后一句結(jié)束時(shí)沒有光標(biāo)閃爍。

import React from 'react';
import PropTypes from 'prop-types';

class CursorImitator extends React.Component {

 static defaultProps = {
   content: [],
   nextLetterTime: 50,
   waitAtEnd: 500,
   waitAtStart: 200,
   blinkSpeed: 130,
   letterWrapClass: ''
 }

 constructor(props) {
   super(props);
   this.loadIntro = this.loadIntro.bind(this);
   this.loadCursorBlink = this.loadCursorBlink.bind(this);
   this.clearAllTimeoutsAndIntervals = this.clearAllTimeoutsAndIntervals.bind(this);
   this.state = {
     mounted: false
   };
   this.ttw = 0;             // Time to Wait.
   this.timeoutList = [];    // List of all timeouts triggered.
 }

 componentDidMount() {
   this.setState({ mounted: true });
 }

 loadIntro(content) {
   const contentLast = content.length - 1;
   return({
         content.map((sentence, index) => {
           const refName = 'line_' + index;
           const isLast = contentLast === index;
           return ({this.state.mounted && this.loadLetter(sentence, refName, isLast)})
         })
       })
 }

 render() {
   const {content, className, style} = this.props;
   return ({this.loadIntro(content)});
 }
}

到目前為止我們做了什么?

  • defaultProps具有屬性的初始值(如果未提供)。

  • content-描述數(shù)組。每個(gè)索引存儲(chǔ)一個(gè)要出現(xiàn)的句子。

  • nextLetterTime-下一個(gè)字母出現(xiàn)之前的時(shí)間。

  • waitAtEnd-每個(gè)句子結(jié)束時(shí)等待的時(shí)間。

  • waitAtStart-每個(gè)句子開始前等待的時(shí)間。

  • blinkSpeed-光標(biāo)出現(xiàn)并重新出現(xiàn)[閃爍]的時(shí)間。

  • letterWrapClass-用于< div >包裝句子的類。

  • constructor()

  • this.ttw-等待時(shí)間是一個(gè)實(shí)例變量,因?yàn)樗仨毘志没?/span>

  • this.timeoutList-觸發(fā)的所有超時(shí)的列表,以便我們可以在需要時(shí)清除。

  • render() -負(fù)載 loadIntro()

  • loadIntro()-對(duì)于每個(gè)句子,我們都迭代并加載字母,但前提是已安裝組件。這是因?yàn)槲覀冃枰妹總€(gè)句子,并且只有在安裝組件之后才會(huì)創(chuàng)建它們。我們正在使用對(duì)每個(gè)句子的div的引用來更新它,而不是將其作為狀態(tài)變量。

下一步:逐個(gè)字母地加載

loadLetter(sentence, refName, isLastSentence) {
   /* To retain content when accessed from within setTimeout */
   let sentenceLength = sentence.length;
   sentence.split('').forEach((letter, index) => {
     let nextLetter = letter;
     let ttw = this.ttw++;
     let reference = refName;
     const {nextLetterTime, waitAtEnd, waitAtStart} = this.props;
     let self = this;
     let currIndex = index;
     /* To create a Blink at the start of every Sentence */
     if (index === 0) {
       this.loadCursorBlink(self.refs[reference], this.ttw);
       this.ttw = this.ttw + (waitAtStart / nextLetterTime);
       ttw = this.ttw;
     }
     const nextTimeout = setTimeout(() => {
       if (self.interval) {
         clearInterval(self.interval);       // Clear any previous Intervals and removing blink
       }
       if (currIndex === 0 && self.refs && self.refs[reference]) { // Adding '|' in the beginning of every sentence and  inserting incoming texts before that
         self.refs[reference].innerText = '|';
       }
       if (nextLetter === ' ' && self.refs && self.refs[reference]) {  // Handling space
         return self.refs[reference][removed] = self.refs[reference][removed].substring(0, self.refs[reference][removed].length - 1) + ' |';
       } else if (self.refs && self.refs[reference]) {                 // adding next digit
         return self.refs[reference].innerText = self.refs[reference].innerText.substring(0,self.refs[reference].innerText.length - 1) + nextLetter + '|';
       }
     }, ttw * nextLetterTime);  // incremented value for every sentence
     this.timeoutList.push(nextTimeout); // To clear it all at once if required
     if (index === sentenceLength - 1) {
       /* To create a Blink at the End of every Sentence */
       this.loadCursorBlink(this.refs[reference], this.ttw, true, isLastSentence);
       this.ttw = this.ttw + (waitAtEnd / nextLetterTime);
     }
   })
 }

loadLetter() 接受3個(gè)參數(shù)。

  • sentence 是出現(xiàn)在單獨(dú)一行上的句子。

  • refName 獲取對(duì)其應(yīng)加載內(nèi)容的div的引用。

  • islastSentence 用于避免最后加載閃爍的光標(biāo)。

在這里,我們應(yīng)該注意閉包,因?yàn)槲覀儗ettimeout不遺漏父范圍的每個(gè)字母。因此,我們使用let和const使其綁定到setTimeout。

this.ttw = this.ttw + (waitAtStart / nextLetterTime);

  • waitAtStart/nextLetterTime 給出迭代次數(shù),之后必須出現(xiàn)下一個(gè)字母。

  • 我們this.ttw為每個(gè)字母遞增。每個(gè)字母出現(xiàn)的時(shí)間是其在this.ttw和中的位置的倍數(shù)nextLetterTime

  • index === 0之所以進(jìn)行檢查,是因?yàn)闊o論何時(shí)我們使用新句子,光標(biāo)都應(yīng)該在開頭閃爍一會(huì)兒。然后我們計(jì)算新的this.ttw時(shí)間,應(yīng)該在眨眼時(shí)間到期之后。

  • nextTimeout保留當(dāng)前觸發(fā)的超時(shí),該超時(shí)在所需時(shí)間過去后觸發(fā),并被推入this.timeoutList以便稍后清除。

  • 在這里,我們清除所有以前的(self.interval如果存在的話),以確保不發(fā)生閃爍。this.interval保留創(chuàng)建的閃爍間隔。

  • currIndex === 0檢查是否已添加“ |” 在每個(gè)句子的開頭,并在前面插入傳入的字母。

  • 如果我們到達(dá)句子的末尾,則最后檢查完成。如果是,我們可以使光標(biāo)閃爍。

loadCursorBlink(ref, ttw, end, isLastSentence) {
 let reference = ref;
 let self = this;
 let isEnd = end;
 const {nextLetterTime, blinkSpeed} = this.props;
 const nextTimeOut = setTimeout(() => {
   if (self.interval) {
     clearInterval(self.interval);
     // 'self.lastReference' stores last shown sentence's reference, we remove the '|' symbol before creating a new interval
     if (self.lastReference && self.lastReference.innerText.substring(self.lastReference.innerText.length-1) === '|') {
       self.lastReference.innerText = self.lastReference.innerText.substring(0, self.lastReference.innerText.length - 1);
     }
   }
   if (!isLastSentence) {
     self.interval = setInterval(() => {
       self.lastReference = reference;
       if (isEnd) {
         if (reference.innerText.substring(reference.innerText.length - 1) === '|') {
           reference.innerText = reference.innerText.substring(0, reference.innerText.length - 1);
         } else if (reference.innerText.substring(reference.innerText.length - 1) !== '|') {
           reference.innerText = reference.innerText + '|';
         }
       } else {
         if (reference.innerText === '|') {
           reference.innerText = '';
         } else if (reference.innerText === '') {
           reference.innerText = '|';
         }
       }
     }, blinkSpeed);
   }
 }, ttw * nextLetterTime);
 this.timeoutList.push(nextTimeOut);}

loadCursorBlink()需要4個(gè)參數(shù)。對(duì)div的引用,等待時(shí)間,句子結(jié)尾以及是否為最后一個(gè)句子。

  • setTimeout 對(duì)于此方法,請(qǐng)保持閃爍出現(xiàn)并消失之后的時(shí)間。

  • nextTimeout保留當(dāng)前觸發(fā)的超時(shí),該超時(shí)在所需時(shí)間過去后觸發(fā),并被推入this.timeoutList以便稍后清除。

  • 在這里,我們清除以前的任何間隔(如果存在)并self.lastReference存儲(chǔ)最后顯示的句子的引用,我們刪除“ |” 符號(hào),然后再創(chuàng)建一個(gè)新間隔。

  • 如果不是最后一句話,則我們按照給定的間隔啟動(dòng)眨眼blinkSpeed。

  • 我們處理句子中所有字母的結(jié)尾和句子中第一個(gè)字母的開頭的眨眼。

componentWillUnmount() {
 this.clearAllTimeoutsAndIntervals()
}

clearAllTimeoutsAndIntervals() {
 if (this.timeoutList) {
   this.timeoutList.forEach((timeout) => {
     clearTimeout(timeout);
   });
 }
 clearInterval(this.interval);
}

clearAllTimeoutsAndIntervals() 如果在啟動(dòng)所有觸發(fā)的超時(shí)之前已卸載組件,則有助于清除所有間隔。