vue3结合socket实现打字机动画
<template>
<div>
<div>ip地址:<input type="text" placeholder="ip地址" v-model="socketIP"></div>
<br />
<div>端口号:<input type="text" placeholder="端口号" v-model="port"></div>
<div>生成条数:<input type="text" placeholder="生成条数" v-model="num"></div>
<br />
<!-- <button>确定</button> -->
<button @click="socketFn()">发送</button>
<div class="writingbox">
<div class="textBox" v-for="(item, index) in textContent['writing']" :key="index">{{ item.editContent }}</div>
</div>
</div>
</template>
<script>
import { reactive, onMounted, toRefs } from 'vue'
import { inject } from "vue";
import { lightHigh, selectSort, del_all, cancelTitleTag, } from '@/libs/utils'
export default {
name: 'socketTest',
components: {},
setup() {
const state = reactive({
socketIP: '192.168.xx.xx',
port: 'xx',
num: 2,
socketEndNum: 1,
socketIndex: 0,
allObj: {},
textListLength: 1,
textContent: {
},
isGenerate: false,
lightword: [],
switch: true,
emitNum: 0
})
const socket = inject("socket");
onMounted(() => { })
const socketFn = () => {
let text = '发送的内容'
let socketEmitNum = 0
// 判断socket是否断开
socket.connected ? '' : socket.open()
// 发送socket的请求条数
for (let i = 0; i < state.num; i++) {
setTimeout(() => {
socket.emit('process', text);
i++
socketEmitNum++
}, 1);
}
state.switch = true
let allArr = []
socket.on('callback', (data) => {
allArr.push(data)
allArr.forEach((item, index) => {
let key = Object.keys(state.allObj)
let isclude = key.includes(item.uuid)
if (isclude) {
if (!state.allObj[item.uuid].includes(item)) {
state.allObj[item.uuid].push(item)
}
} else {
state.allObj[item.uuid] = []
state.allObj[item.uuid].push(item)
}
})
// 根据uuid进行分类,
// console.log("socketEmitNum", socketEmitNum, Object.keys(state.allObj).length);
if (state.switch && (socketEmitNum === Object.keys(state.allObj).length)) {
testFn(state.allObj)
}
// 当数据返回结束时
if (data.is_end) {
if (state.socketEndNum < state.num) {
state.socketEndNum++
} else {
state.socketEndNum = 1
allArr = []
// obj = {}
socketEmitNum = 0
}
}
});
}
const testFn = (obj) => {
state.switch = false
let fnobj = JSON.parse(JSON.stringify(obj))
console.log("obj", obj);
console.log("fnobj", fnobj);
let keys = Object.keys(fnobj)
// console.log("keys",keys);
let params = {
num: state.num
}
// 初始化数据:
for (let i = 0; i < params.num; i++) {
state.textContent['writing'].push({
count: 0,
card_new: true,
editContent: '',
content: lightHigh(
'',
selectSort(state.lightword),
false
)
.replace(/<p>/gi, '')
.replace(/<\/p>/gi, ''),
picture: [],
pictureSize: [],
video: [],
videolighWord: [],
videoImg: '',
imglighWord: [],
opacity: '#1A1A1A',
tapOpacity: '#244EA4',
titleOpacity: '#000000',
img2failShow: false,
img2textShow: false,
video2failShow: false,
video2failStatus: [
'视频生成时间过长',
'可稍后在历史记录中查看完成视频'
],
video2loadingShow: false,
editContentStatus: true,
socketIndex: 0,
isWriting: false,
datalength: 0,
cacheShow: true,
uuid: keys[i],
socketCacheData: []
})
}
state.isGenerate = true
//最后再遍历一遍存入的内容,调整需要展示的参数信息
state.textContent['writing'].forEach((item, index) => {
// state.gptCatch[index] = {}
// state.gptCatch_count[index] = 1
item.content = lightHigh(
item.content ? item.content : '',
selectSort(state.lightword),
false
)
.replace(/<p>/gi, '')
.replace(/<\/p>/gi, '')
item.title = ''
let babel = ''
if (item?.tags) {
item?.tags?.forEach((item) => {
item = ' #' + item + ' '
babel = babel + item
})
}
item.index = index
item.babel = lightHigh(
babel,
selectSort(state.lightword),
false
)
item.word_count = 0
item.count = del_all(
cancelTitleTag(item.content + item.babel + item.title)
).length
item.rateValue = ''
item.copyImg = ''
// item.copyImg = require('../../assets/images/text2img_copy.svg')
item.copyStarWrod = '标记灵感'
item.copyWroddone = false
item.tagsShow = true
item.loading = false
item.dotShow = false
item.text = ''
item.socketIndex = 0
item.isWriting = false
item.isEnd = false
if (!item.show_id && !item.content) {
item.socketCacheData = obj[item.uuid]
}
})
socketHandleFn(state.textContent['writing'])
}
// 一段一段处理socket返回的值
const socketHandleFn = (textContent) => {
textContent.forEach((item, index) => {
if (!item.show_id && !item.content) {
writingTxet(item, index)
}
})
}
// 将socket中的某一数据中的data进行切割成数组传给writingWord
const writingTxet = (item, ind) => {
if (item.socketCacheData[item.socketIndex]?.is_end) {
item.isEnd = true
}
if (item.socketCacheData[item.socketIndex]?.data === 1) {
item.editContent += item.socketCacheData[item.socketIndex]?.data
item.socketIndex++
writingTxet(item, ind)
} else {
let textDataArr = item.socketCacheData[item.socketIndex]?.data.split("")
writingWord(textDataArr, ind, 0, item)
item.socketIndex++
}
}
// 打字机动画效果
const writingWord = async (textDataArr, ind, i, item) => {
// 当打字速度过快时,socket数据没来得及返回,导致textDataArr为undefined,进行异常捕获
try {
if (i < textDataArr.length) {
item.editContent += textDataArr[i]
await new Promise(resolve => { setTimeout(resolve, 0) })
await writingWord(textDataArr, ind, ++i, item)
} else if (item.socketCacheData.length - 1 === item.socketIndex && item.isEnd) {
item.editContent = item.editContent + "----" + item.uuid
// console.log("打印完成", state.allObj);
delete state.allObj[item.uuid]
// console.log("删除后", state.allObj);
}
else {
// console.log("=============");
await writingTxet(item, ind)
}
} catch (error) {
// console.log("error", ind, textDataArr);
setTimeout(() => {
if (!item.isEnd) {
writingTxet(item, ind)
// console.log("writingTxet", item, ind);
}
}, 2000);
}
}
return {
...toRefs(state),
socketFn
}
}
}
</script>
<style lang="less" scoped>
input {
border: 1px solid;
}
.writingbox {
width: 500px;
// height: 800px;
// border: 1px solid;
margin: 0 auto;
.textBox {
width: 500px;
min-height: 100px;
border: 1px solid red;
margin: 10px 0;
}
}
</style>
posted on 2023-10-09 15:25 IT丶Hatcher 阅读(319) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通