React流式打字效果实现(不需要CSS) - Typing Effect with out use Css

前言

最近有个云栖大会的demo展示需求,要实现个类似的打字效果,所以我找了找相关的库。找到一个还不错的~叫iTyped.js。但是最终的效果和我想要的不太一样,会有回删效果,看了下源码,所以就自己写了一个~

再夸奖下 iTyped.js 只有3K,非常小而美,完全靠JS实现的效果!

 

最终效果

边播放语音,边出现文字的打字效果,gif 效果如下~

源码分享

变量设置

//全局 变量设置 - 如果想要速度不一致也可以写成内部变量
const typingRate = 250;


//内部 变量设置
    constructor(props) {
        super(props);
        this.state = {
            //打字出的文字
            textAreaShow: "",
            // 是否在打字中
            isTyping: false,
            //等待被打字的数组
            waitToType: [],
            //延迟打字开始的时间
            delayTime: this.props.delayTime || false,
        }
    }

打字函数

 /**
     * 打字函数
     * @param  {[type]} stringAll 打印的总字符
     * @param  {[type]} char      目前的打印的字符
     * @param  {[type]} nowPosition 现在的打印的位置
     * @return {[type]}           [description]
     */
    typing(stringAll, char, nowPosition) {
        // 如果打印位置小于 字符串总长度
        // 还是在打印中 isTyping :true
        // textAreaShow 字符串增加一个字符
        // 继续 打印下一字符
        if (nowPosition < stringAll.length) {
            let textAreaShow = this.state.textAreaShow + char;
            this.setState({
                textAreaShow: textAreaShow,
                isTyping: true,
            }, () => {
                setTimeout(() => this.typing(stringAll, stringAll[nowPosition + 1], nowPosition + 1), typingRate);
            }, this)
        }
        // 已经打印完毕了
        // isTyping 设置为 false
        // 查看数组中是否还有未打印的,如果有就打印
        else if (nowPosition >= stringAll.length) {
            this.setState({
                isTyping: false,
            }, () => {
                let waitToType = this.state.waitToType;
                if (waitToType.length > 0) {
                    let stringInput = waitToType.shift();
                    setTimeout(() => this.typing(stringInput, stringInput[0], 0), typingRate);
                    this.setState({
                        waitToType: waitToType
                    })
                }
            }, this)
        }
    }

流式打字效果冲突处理

流式的的不同,增加了是否在打印中的判断

如果 “在打印中” 就放到等待打印的数组中,避免 打印效果错乱

    componentWillReceiveProps(nextProps) {
        // 需要打印的数组
        let textArea = nextProps.textArea;
        // 之前需要打印的数组
        let befTextArea = this.props.textArea || [];
        // 等待打印的数组,方便setState
        let waitToType = JSON.parse(JSON.stringify(this.state.waitToType));
        // 等待打印的字符
        let stringAll;
        // 切换时,重置
        if (textArea.length === 0) {
            this.setState({
                textAreaShow: "",
                waitToType: [],
            })
        }

        // 初始化的时候,直接打印
        if (this.state.textAreaShow === "" && this.state.delayTime && textArea.length > 0 && textArea.length > befTextArea.length) {
            stringAll = textArea[textArea.length - 1];
            // waitToType.push(stringAll);
            setTimeout(() => this.typing(stringAll, stringAll[0], 0), typingRate + this.state.delayTime);
        } 
        // 如果正在打印,把 字符串 推入 waitToType数组中
        else if (textArea.length > 0 && textArea.length > befTextArea.length) {
            stringAll = textArea[textArea.length - 1];
            if (this.state.isTyping) {
                waitToType.push(stringAll);
                this.setState({
                    waitToType: waitToType
                })
            } else {
                setTimeout(() => this.typing(stringAll, stringAll[0], 0), typingRate);
            }
        }
    }

Codepen DEMO

https://codepen.io/CandyQiu/pen/gywZKw

资料参考

1. iTyped:https://github.com/luisvinicius167/ityped

猜你喜欢

转载自blog.csdn.net/Candy_home/article/details/89093059
今日推荐