/src/utils/emojiMap.js //表情库请自行寻找
//表情图片地址
//例如 emojiUrl + 'emoji_141@2x.png'
export const emojiUrl = ''
export const emojiMap = {
'[龇牙]': 'emoji_141@2x.png'
}
export const emojiName = [
'[龇牙]',
]
/src/utils/decodeText.js 字符串转换成字符串和图片的数组 例如 你好[龇牙]转换成['你好',emojiUrl + 'emoji_141@2x.png']用于循环显示表情和文本的内容
import { emojiMap, emojiUrl } from '@/utils/emojiMap'
export function decodeText (text) {
let renderDom = []
// 文本消息
let temp = text
let left = -1
let right = -1
while (temp !== '') {
left = temp.indexOf('[')
right = temp.indexOf(']')
switch (left) {
case 0:
if (right === -1) {
renderDom.push({
name: 'text',
text: temp
})
temp = ''
} else {
let _emoji = temp.slice(0, right + 1)
if (emojiMap[_emoji]) {
renderDom.push({
name: 'img',
src: emojiUrl + emojiMap[_emoji]
})
temp = temp.substring(right + 1)
} else {
renderDom.push({
name: 'text',
text: '['
})
temp = temp.slice(1)
}
}
break
case -1:
renderDom.push({
name: 'text',
text: temp
})
temp = ''
break
default:
renderDom.push({
name: 'text',
text: temp.slice(0, left)
})
temp = temp.substring(left)
break
}
}
return renderDom
}
使用
<template>
<div>
<div class="flex box" style="margin-bottom: 4px; position: relative">
<div
v-if="faceFlag"
style="position: absolute; top: -250px; z-index: 100"
>
<div class="boxs" style="padding: 20rpx 30rpx">
<div
v-for="item in emojiName"
class="emoji"
:key="item"
@click.stop="chooseEmoji(item)"
>
<img
:src="emojiUrl + emojiMap[item]"
style="width: 20px; height: 20px"
/>
</div>
</div>
</div>
<img
class="icon cur"
src="@/assets/png/addFace.png"
mode=""
@click.stop="openFaceFun"
style="margin-right: 10px"
/>
<div style="position: relative; margin-right: 10px">
<input
type="file"
id="imagePicker"
accept="image/*"
class="inpt"
@click="faceFlag = false"
@change="sendFun($event, 'image')"
title=""
/>
<img class="icon cur" src="@/assets/png/addPic.png" mode="" />
</div>
<div style="position: relative; margin-right: 10px">
<input
type="file"
id="videoPicker"
accept="video/*"
class="inpt"
@click="faceFlag = false"
@change="sendFun($event, 'video')"
title=""
/>
<img class="icon cur" src="@/assets/png/addVideo.png" mode="" />
</div>
</div>
<el-input
v-model="textarea"
:rows="2"
type="textarea"
placeholder="Please input"
/>
<el-button @click="sendFun(textarea, 'msg')">发送</el-button>
<div>
<div v-for="(item, index) in msgArr" :key="index">
<template v-if="item.type == 'msg'">
<div class="flex text-box">
<div v-for="(i, k) in decode(item.content)" :key="k">
<div class="font" v-if="i.name === 'text'">{{ i.text }}</div>
<img v-else-if="i.name === 'img'" :src="i.src" class="imgbox" />
</div>
</div>
</template>
<template v-else-if="item.type == 'image'">
<img :src="item.content" alt="" />
</template>
<template v-else>
<video :src="item.content" controls></video>
</template>
</div>
</div>
</div>
</template>
<script>
import { emojiMap, emojiName, emojiUrl } from '@/utils/emojiMap'
import { decodeText } from '@/utils/decodeText'
export default {
data() {
return {
textarea: '',
msgArr: [],
faceFlag: false,
emojiMap,
emojiName,
emojiUrl,
}
},
methods: {
openFaceFun() {
this.faceFlag = !this.faceFlag
},
openOperFun() {
console.log(222)
this.faceFlag = false
},
chooseEmoji(e) {
this.textarea += e
this.faceFlag = false
},
decode(text) {
return decodeText(text)
},
sendFun(e, type) {
let obj = {
type,
content:
type == 'msg' ? e : window.URL.createObjectURL(e.target.files[0]),
}
this.msgArr.push(obj)
if (type == 'msg') this.textarea = ''
},
},
}
</script>
<style lang='scss' scoped>
.inpt {
position: absolute;
top: 0;
height: 100%;
width: 100%;
opacity: 0;
padding: 0;
}
.boxs {
background-color: #fff;
height: 250px;
overflow-y: scroll;
transition: all 1s ease-in-out;
display: flex;
flex-wrap: wrap;
align-items: flex-start;
justify-content: space-between;
}
.emoji {
margin: 5px 7.5px;
}
.imgbox {
width: 20px;
height: 20px;
}
.font {
font-size: 20px;
}
.text-box {
align-items: center;
}
</style>
展示效果
样式没有写的很多,请自行调整
表情
图片、视频(实际应用的时候,图片视频是需要上传到服务器的,本文没有写,可以去看看我的另一篇上传组件)