uniapp APP端实现打字机效果

uniapp APP端实现打字机效果 使用插件fetch-event-source加上renderjs

打字机效果是在各个AI模型中都会看到的,数据传输主要是用sse,接口返回的数据是带markDown格式的字段(以下简称md字段),本文章主要将在安卓环境下的实现,仅供参考😀

打字机效果

打字机的实现是参考另一个大佬文章中的,直接使用,大佬的是ts版本,我的是js版本

js
复制代码
// 打字机队列 export class Typewriter { queue = [] consuming = false constructor(onConsume) { this.onConsume = onConsume } // 输出速度动态控制 dynamicSpeed() { const speed = 2000 / this.queue.length if (speed > 200) { return 200 } else { return speed } } // 添加字符串到队列 add(str) { if (!str) return str = str.replaceAll('\n', 'n'); this.queue.push(...str.split('')); } // 消费 consume() { if (this.queue.length > 0) { const str = this.queue.shift() str && this.onConsume(str) } } // 消费下一个 next() { this.consume() // 根据队列中字符的数量来设置消耗每一帧的速度,用定时器消耗 this.timmer = setTimeout(() => { this.consume() if (this.consuming) { this.next() } }, this.dynamicSpeed()) } // 开始消费队列 start() { this.consuming = true this.next() } // 结束消费队列 done() { this.consuming = false clearTimeout(this.timmer) // 把queue中剩下的字符一次性消费 this.onConsume(this.queue.join("")) this.queue = [] } }
  • 引入使用
js
复制代码
import { Typewriter } from '@/utils/typeWriter.js';

由于uniapp 无法使用sse,需要使用到插件fetch-event-source加上renderjs

使用renderjs

使用rederjs 可参考uniapp官网 renderjs | uni-app官网 (dcloud.net.cn)

但是其中直接获取逻辑层option的值的写法只有在h5页面才生效,在APP端用不了,那如何取逻辑层的数据呢?

uniapp APP端实现打字机效果

获取逻辑层的数据

由于使用了renderjs,可以使用document
在逻辑层定义数据绑定在一个元素上(这个元素专门拿来传输数据),用document获取元素,再使用getAttribute去获取定义的数据

js
复制代码
//自定义数据绑定元素 <view id="transmit" :data-url="typeWriterUrl" :data-uid="curUid" :data-trainId="trainId" ></view> //获取数据 let typeWriterView = document.getElementById('typeWriterView') let url = transmit.getAttribute("data-url"); let uid = transmit.getAttribute("data-uid"); let fitnessAssessmentId = transmit.getAttribute("data-trainId");

那逻辑层的数据如何驱动renderjs的数据呢 可以绑定数据在元素上,:isInvoke="isInvoke"
使用:change:isInvoke="typeWriterRender.receiveMsg"renderjs中使用监听事件监听数据的变化
其中typeWriterRender对应renderjs中声明的modulereceiveMsg是对应监听事件

js
复制代码
//元素 <view id="transmit" :data-url="typeWriterUrl" :data-uid="curUid" :data-trainId="trainId" :isInvoke="isInvoke" :change:isInvoke="typeWriterRender.receiveMsg"></view> //renderjs中 receiveMsg 监听事件 receiveMsg(newValue, oldValue, ownerVm, vm) {}

使用fetch-event-source

  • 安装fetch-event-source
js
复制代码
npm install @microsoft/fetch-event-source
  • 引入fetch-event-source
js
复制代码
import { fetchEventSource } from '@microsoft/fetch-event-source';
  • 使用fetch-event-source 进行post请求

uniapp APP端实现打字机效果

使用markdown-it

  • 安装markdown-it
js
复制代码
npm install markdown-it
  • 使用
js
复制代码
import MarkdownIt from 'markdown-it'; //初始化 let md = MarkdownIt({ html: true, linkify: true, typographer: true, });

总体实现

js
复制代码
//new 一个打字机类的对象 生成html typeWriterSelf = new Typewriter((str) => { htmlmd += str; //获取元素 let typeWriterView = document.getElementById('typeWriterView') //md字段转成html let html = md.render(htmlmd); //直接设置html typeWriterView.innerHTML = html; }); //初始化 typeWriterSelf.start(); //监听接口返回的数据 添加到打字类中 const ctrl = new AbortController(); fetchEventSource(url + '/xxx/xxx', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ uid, fitnessAssessmentId }), signal: ctrl.signal, onmessage(msg) { if (msg.event === '') { var result = msg.data; //获取数据添加 typeWriterSelf.add(result); } else if (msg.event === 'close') { ctrl.abort(); } }, onerror(err) { console.log('err=>>>',err); throw err; //必须throw才能停止 } });

参考文章

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

给TA打赏
共{{data.count}}人
人已打赏
人工智能

Sora :新一代文本转视频工具

2024-5-30 17:41:08

人工智能

prompt于AI,正如菜单于大厨

2024-5-30 21:43:05

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索