uniapp APP端实现打字机效果

打字机效果是在各个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端用不了,那如何取逻辑层的数据呢?

获取逻辑层的数据

由于使用了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请求

使用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才能停止
				}
			});

参考文章

相关推荐
用户68370935955几秒前
在 Rokid AR 眼镜里玩消消乐:基于 Unity 2022 LTS + UXR 3.0 SDK 的轻量级 AR 游戏尝试
前端
zzjyr2 分钟前
@umijs/max 中导出的 request 方法,如何实现 GET/POST/PUT/DELETE 这四种核心请求
前端
swipe2 分钟前
#用这 9 个浏览器 API,我把页面从“卡成 PPT”救回到 90+(每个都有能直接抄的例子)
前端·javascript·面试
zzjyr4 分钟前
基于 @umijs/max 的 request 补充常见错误统一处理、请求取消、重复请求防抖的完整方案
前端
拖拉斯旋风16 分钟前
深入浅出 RAG:从网页爬取到智能问答的完整链路解析
前端
Mintopia29 分钟前
Vite 发展现状与回顾:从“极致开发体验”到生态基础设施
前端
前端双越老师1 小时前
前端面试常见的 10 个场景题
前端·面试·求职
孟祥_成都2 小时前
【全网最通俗!新手到AI全栈开发必读】 AI 是如何进化到大模型的
前端·人工智能·全栈
牛奶2 小时前
AI辅助开发的基础概念
前端·人工智能·ai编程
摸鱼的春哥2 小时前
Agent教程15:认识LangChain,Agent框架的王(上)
前端·javascript·后端