背景
最近产品让我们在一个聊天的界面系统回复的时候做一个类似chatGPT打字的效果
我思考了下有几种方案
- 让后端一个一个字给我返回
- 后端一次性返回给我前端对字符串切割
但是呢,后端一个一个字返回其实也有很多问题,比如说怎么样才知道一段话结束了,返回是用用SSE还是用webcocket,本来页面上的对话就是 我问机器人一个问题,然后机器人去数据库里面找到一样或者类似的答案一次性返回就好,实现起来也比较简单,如果一个一个字返回后端同事的改造成本比较高。
技术预研
我们先考虑一个简单的文本如何让他看起来一个一个的输入在屏幕上呢,原理就是指定一个dom元素,然后由少到多的在dom元素中插入文字,所以我们可以用一个数组把由少到多的文字放进去
比如一段文本是: 我是一段普通的文本
那么在渲染数组renderList里面他的值应该就是:
['我是一段普通的文本', '我是一段普通的文', '我是一段普通的', '我是一段普通', '我是一段普', '我是一段', '我是一', '我是', '我', '']
这样我们渲染的时候就用一个定时器,对renderList进行出栈操作就好了,生成这样一个数组就是对文本进行切割
ok ,说明打印效果前端是可以实现的,那么如何实现一个带有样式的富文本呢(我们的业务场景下没有图片和表格)
实现富文本的打印效果
假定一个富文本 str = "<div class="wrapper"><a href="https://baidu.com" >我是一个指向百度的超链接</a> <div style="color:red;"><span style="color:green;">我的字体颜色是绿色</span> 我的字体颜色是红色</div></div>"
如何在富文本中拿到纯文字呢?
想把字符串中提出标签的内容有一个很简单的方案,把富文本插入到页面真实的dom中,然后通过 dom.innerText 拿到富文本
或者可以用正则表达式的方式把标签名称全部去掉
所以富文本的所有文字数组
就是
html.replace(/<[^>]+>/g,'').split("")
如何生成富文本的渲染数组renderList
针对简单的文本我们很简单的就生成了renderList,富文本怎么弄呢
我们是不是可以从后往前遍历fonts的时候把当前遍历的font 在富文本中给他删掉 就好了?
代码
不足和遗憾
其实笔者还在思考一个问题,如果有表格和图片的时候以及元素有padding 和背景色的时候如何处理,我暂时还想不到有什么办法可以比较好解决。