前言
表情包是聊天系统中一个比较常见的功能。常见的表情表分为两种是类型。
一种是Unicode表情,另外一种是图片表情。我们这篇文章两种都会涉及。
图片类表情包会涉及到编解码。不会将发送消息的图片的url地址也一并存入数据库中。
文章将会从表情分类。表情编解码。表情展示等方面来分享。还有就是分享一下表情包后台的数据结构。比如允许用户自己创建表情包之类的功能。
目前已经写的文章有。并且有对应视频版本。关注我的B站查看视频。
git项目地址 【IM即时通信系统(企聊聊)】点击可跳转
分布式websocket即时通信(IM)系统构建指南【第七期】
分布式websocket即时通信(IM)系统保证消息可靠性【第八期】
分布式websocket IM聊天系统相关问题问答【第九期】
什么?websocket也有权限!这个应该怎么做?【第十期】
分布式ID是什么,以美团Leaf为例改造融入自己项目【第十一期】
IM聊天系统为什么需要做消息幂等?如何使用Redis以及Lua脚本做消息幂等【第12期】
微信发送一条消息经历哪些过程。企业微信以及钉钉的IM架构对比【第13期】
微信群为什么上限是500人,IM设计系统中的群聊的设计难点【第14期】
【分布式websocket】RocketMQ发送消息保证消息最终一致性需要做哪些处理?【第15期】
【分布式websocket】群聊中的各种难点以及解决推拉结合【第16期】
【分布式webscoket】未读消息如何设计?解决缓存与数据库数据一致性!推送未读消息流程【第17期】
IM系统客户端消息存储在手机电脑浏览器分别存储在什么地方?对消息加密策略?如何保证服务端消息和客户端消息一致性【第18期】
【分布式websocket 】前端vuex管理客户端消息crud!使用localStorage来存储【第19期】
vant官网
https://vant-contrib.gitee.io/vant/v3/#/zh-CN/popup
设计过程
是否需要存储数据库
存储URL到数据库的情况:
- 表情自定义性高:如果你的IM系统允许用户上传自定义表情,那么每个表情的URL都是唯一的,需要存储到数据库中以便检索和显示。
- 动态表情包:如果系统支持动态添加或更新表情包,那么表情的URL可能会变化,存储URL到数据库可以方便管理和更新。
- 访问控制:如果某些表情需要根据用户权限显示(如VIP表情),则可能需要将表情的URL和权限信息存储到数据库中,以便进行权限验证。
不需要存储URL到数据库的情况: - 固定的表情集:如果你的系统使用的是一组固定的、预先定义好的表情,且这些表情不会频繁变更,那么可以将表情的URL硬编码在客户端或服务器的配置文件中,而不是存储在数据库里。
- 简化设计:为了简化数据库设计和减少数据库操作,如果表情的管理和使用相对简单,可以考虑不将URL存储在数据库中。
实现示例
对于不存储URL到数据库的设计,你可以在客户端或服务器上维护一个表情的映射表,将特定的标记映射到对应的URL。例如,使用一个JSON对象存储表情的标记和URL:
对于固定和简单的表情系统,不存储URL可能是一个更简洁高效的选择。
数据库字符集设置
要在Java应用程序中通过数据库连接支持存储和检索表情符号(如Unicode中的Emoji),确实需要注意数据库的字符集配置,特别是对于MySQL数据库。以下是一些关键的注意事项:
- 使用MySQL 5.5.3及以上版本
从MySQL 5.5.3版本开始,引入了utf8mb4字符集,它支持存储4字节的Unicode字符。这对于存储表情符号是必需的,因为许多表情符号(包括所有新的表情符号)需要4字节的Unicode编码。如果使用utf8字符集(最多只支持3字节的Unicode字符),则无法存储这些表情符号。 - 使用utf8mb4字符集
为了在MySQL数据库中支持表情符号,你需要确保数据库、表和连接使用utf8mb4字符集。这包括:
数据库字符集:创建数据库时指定utf8mb4字符集。
CREATE DATABASE mydatabase CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
表字符集:创建表时指定utf8mb4字符集。
CREATE TABLE mytable (
id INT PRIMARY KEY,
text VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
);
连接字符集:确保Java应用程序与MySQL数据库的连接使用utf8mb4字符集。如果使用JDBC连接MySQL,可以在连接URL中指定字符集参数
String url = "jdbc:mysql://localhost:3306/mydatabase?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
支持表情符号存储的关键是使用utf8mb4字符集。确保数据库、表和连接都正确配置了这个字符集。此外,考虑使用MySQL的较新版本以获得更好的性能和特性支持。在Java应用程序中,通过JDBC连接时,确保连接字符串正确配置了字符编码参数。
流程
- 表情包资源准备
收集或设计表情图片:首先需要一组表情图片,可以是通用的表情符号,也可以是特定主题的自定义设计。
优化图片:为了提高加载速度和减少数据传输量,应对图片进行压缩和优化。
存储:将表情图片存储在服务器上,可以使用CDN(内容分发网络)来加速全球的访问速度。 - 数据库设计
设计数据库来管理表情包和表情图片。一个基本的设计可能包括两个表:一个用于存储表情包信息,另一个用于存储表情图片信息。 - 前端实现
表情选择界面:在IM客户端中实现一个表情选择界面,用户可以浏览和选择表情包中的表情。
表情显示:在消息输入框和聊天记录中,支持显示选中的表情图片。
快捷输入:(可选)支持通过特定的快捷方式(如输入)来快速插入表情。 - 消息处理
表情编码:当用户发送包含表情的消息时,需要将表情转换为一种编码形式(如特定的标记或URL),以便在接收端正确解析和显示。
表情解码:在消息接收端,解析消息内容中的表情编码,将其转换回对应的表情图片进行显示。 - 示例代码
假设用户选择了一个表情,前端将表情编码为特定的标记或URL,发送到服务器。在接收端,解析这些标记并显示对应的表情图片。
发送端:
// 假设用户选择了一个笑脸表情
const message = "你好啊 ";
// 将表情转换为编码或URL(这里仅为示例,实际实现可能会复杂)
const encodedMessage = "你好啊 [emoji:smile]";
// 接收到的消息
const receivedMessage = "你好啊 [emoji:smile]";
// 解析消息中的表情编码,将其替换为标签显示表情图片
const displayedMessage = receivedMessage.replace(/[emoji:(w+)]/g, '');
- 注意事项
性能优化:考虑使用雪碧图(CSS Sprite)或WebP格式来减少HTTP请求和优化图片加载。
兼容性:确保表情图片在不同设备和平台上都能正确显示。
用户体验:提供易于使用的表情选择界面,支持搜索和分类浏览表情包。
聊天框前端样式
!-- 底部表情包 -->
div class="nav-bar-chat ">
ul class="nav-list">
div class="nav-list-item">
span @click="toggleEmojiPanel">/span>
/div>
div class="nav-list-item">
span @click="toggleEmojiPanel">拍摄/span>
/div>
div class="nav-list-item">
span @click="toggleEmojiPanel">图片/span>
/div>
div class="nav-list-item">
span @click="toggleEmojiPanel">文件/span>
/div>
div class="nav-list-item">
span @click="toggleEmojiPanel">语音/span>
/div>
div class="nav-list-item">
span @click="toggleEmojiPanel">视频/span>
/div>
/ul>
div v-if="showEmojiPanel" class="emoji-panel">
van-grid column-num="5">
van-grid-item
v-for="(emoji, index) in emojis"
:key="index"
@click="addEmoji(emoji)"
>
van-image
v-if="emoji.src"
width="35px"
height="35px"
fit="cover"
:src="emoji.src"
/>
div v-if="!emoji.src">{{ emoji.name }}/div>
!-- img :src="emoji.src" :alt="emoji.name" class="emoji-img" /> -->
/van-grid-item>
/van-grid>
/div>
/div>
更新脚本逻辑
添加或修改方法来控制表情面板的显示和隐藏。
//切换表情面板
const toggleEmojiPanel = function() {
state.showEmojiPanel = !state.showEmojiPanel; // 切换表情面板的显示状态
};
//添加表情
const addEmoji = function(emoji) {
if (emoji.type == "pic") {
state.content += emoji.encode;
} else {
state.content += emoji.name;
}
// 简化处理,实际应用中可能需要特殊处理
state.showEmojiPanel = false; // 选择表情后关闭面板
};
通过这种方式,表情面板将作为聊天输入框的直接扩展。用户可以通过点击表情按钮来显示或隐藏表情面板,并从中选择表情添加到输入框中。
表情包json
//表情包
showEmojiPanel: false, // 控制表情包面板的显示
emojis: [
{ id: "1", type: "base", name: "" },
{ id: "2", type: "base", name: "" },
{ id: "3", type: "base", name: "" },
{ id: "4", type: "base", name: "" },
{ id: "5", type: "base", name: "" },
{ id: "6", type: "base", name: "" },
{ id: "7", type: "base", name: "" },
{ id: "8", type: "base", name: "" },
服务器托管网 { id: "9", type: "base", name: "" },
{ id: "10", type: "base", name: "" },
{ id: "11", type: "base", name: "" },
{ id: "12", type: "base", name: "" },
{ id: "131", type: "base", name: "⚡" },
{ id: "14", type: "base", name: "" },
{ id: "15", type: "base", name: " " },
{
id: "16",
type: "pic",
name: " 头像 ",
src:
"https://edu-renyun.oss-cn-beijing.aliyuncs.com/2021/07/26/a10016be5a4348a885bc79bb7bf78ad4logo1.png",
encode: "[emoji:avatar]",
},
{
id: "17",
type: "pic",
name: " 头像 2",
src:
"https://edu-renyun.oss-cn-beijing.aliyuncs.com/2021/07/26/0ea48cb529e54573ae791ffbde3fcd9fu=2095913610,1514262792&fm=26&gp=0.jpg",
encode: "[emoji:avatar2]",
},
// 更多表情...
],
前端显示表情包方案
通过v-html来解析包含标签的消息内容。解码的时候转换成url地址。
div
ref="contentArea"
v-html="decodeCodeToEmoji(item.content)"
>/div>
封装函数
为了实现点击图片将其转换为特定编码(例如[emj])并在聊天消息框中显示,然后在显示时将编码解码为标签的功能,你可以创建两个函数:encodeEmojiToCode和decodeCodeToEmoji。以下是如何封装这两个函数的示例:
// 将特定编码转换为标签用于显示
const decodeCodeToEmoji = function(message) {
const avatarRegex = /[emoji:avatar(d+)?]/g;
let match;
const avatars = state.emojis;
while ((match = avatarRegex.exec(message)) !== null) {
// const avatarIndex = match[1]; // 获取头像编号 // 获取头像自定义标识符("avatar" 或 "avatar2")
const avatar = avatars.find((a) => a.encode === match[0]); // 查找对应的头像信息
if (avatar) {
message = message.replace(
match[0],
`img src="${avatar.src}" style="width: 25px; height: 25px; border-radius: 50%;" alt="${avatar.name}" />`
);
}
}
return message;
};
使用编码和解码函数
当用户点击一个表情图片时,你可以调用encodeEmojiToCode函数将图片转换为编码,并将这个编码添加到聊天输入框的内容中。在发送消息或将消息显示到聊天界面时,使用decodeCodeToEmoji函数将编码转换回标签。
//添加表情
const addEmoji = function(emoji) {
if (emoji.type == "pic") {
state.content += emoji.encode;
} else {
state.content += emoji.name;
}
// 简化处理,实际应用中可能需要特殊处理
state.showEmojiPanel = false; // 选择表情后关闭面板
};
div
ref="contentArea"
v-html="decodeCodeToEmoji(item.content)"
>/div>
自定义表情包结构设计
CREATE TABLE yan_im_emoji_packs (
pack_id INT AUTO_INCREMENT PRIMARY KEY,
pack_name VARCHAR(255) NOT NULL,
description TEXT,
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE yan_im_emojis (
emoji_id INT AUTO_INCREMENT PRIMARY KEY,
pack_id INT,
emoji_url VARCHAR(255) NOT NULL,
shortcut VARCHAR(50), -- 可选,用于快速输入的快捷方式
FOREIGN KEY (pack_id) REFERENCES emoji_packs(pack_id) ON DELETE CASCADE
);
这块留一个小尾巴
聊天发送消息的框其实是一个简易的富文本编辑器。因为聊天消息框支持换行,支持显示表情,支持复制粘贴等功能就是一个简易的富文本编辑器。引用其他的组件样式方面和实用性方面不太好。所以计划自己写。待做
创建富文本编辑器
- 创建富文本编辑器组件
首先,创建一个新的 Vue 组件 RichTextEditor.vue:
template>
div class="rich-text-editor">
div class="toolbar">
!-- 表情按钮 -->
van-button icon="smile-o" @click="insertEmoji">表情/van-button>
/div>
div
ref="editor"
class="editor"
contenteditable="true"
@input="updateContent"
@blur="updateContent"
>/div>
/div>
/template>
script>
export default {
data() {
服务器托管网 return {
content: '',
};
},
methods: {
insertEmoji() {
// 示例:插入一个静态表情图片
const imgHtml = 'img src="path/to/your/emoji.png" alt="emoji" class="emoji">';
this.$refs.editor.innerHTML += imgHtml;
this.updateContent();
},
updateContent() {
this.content = this.$refs.editor.innerHTML;
// 在这里,你可以发出事件,将内容同步到父组件或进行保存
this.$emit('update:content', this.content);
},
},
};
/script>
style scoped>
.rich-text-editor .editor {
border: 1px solid #ccc;
min-height: 100px;
padding: 10px;
margin-top: 10px;
}
.emoji {
width: 24px;
height: 24px;
}
/style>
- 使用富文本编辑器组件
在你的页面或父组件中引入并使用这个富文本编辑器组件:
template>
div>
rich-text-editor @update:content="handleContentUpdate">/rich-text-editor>
/div>
/template>
script>
import RichTextEditor from './RichTextEditor.vue';
export default {
components: {
RichTextEditor,
},
methods: {
handleContentUpdate(content) {
console.log('Updated content:', content);
// 处理更新的内容,例如保存到数据或发送到服务器
},
},
};
/script>
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
相关推荐: Gin 中使用 base64Captcha 生成图形验证码
验证码库 https://github.com/mojocn/base64Captcha 中文文档 Go进阶37:重构我的base64Captcha图形验证码项目 | ❤️ 在models文件夹中写一个验证码的文件,Captcha.go package mod…