当前位置: 首页 > news >正文

vue3+ts封装类似于微信消息的组件

组件代码如下:

<template><div:class="['voice-message', { sent: isSent, received: !isSent }]":style="{ backgroundColor: backgroundColor }"@click="togglePlayback"><!-- isSent为false在左侧,为true在右侧--><!-- 语言条要按照语音时长显示不同的宽度,所以增加了一块宽度,发送者的时候,加在左侧,接收者的时候,加在右侧--><div v-if="isSent" :style="`width:${(duration / 10) * 30}px`"></div><span class="duration" v-if="isSent">{{ duration }}''&nbsp;</span><div :class="['voice-icon', { 'sent-icon': isSent }]"><div :class="['small']" :style="smallStyle"></div><div :class="['middle', { animate: isPlaying }]" :style="middleStyle"></div><div :class="['large', { animate: isPlaying }]" :style="largeStyle"></div></div><span class="duration" :style="{ color: iconColor }" v-if="!isSent">{{ duration }}&nbsp;''</span><div v-if="!isSent" :style="`width:${(duration / 10) * 30}px`"></div></div>
</template><script setup lang="ts">
import { ref, computed, withDefaults, onBeforeUnmount } from "vue";// 使用 withDefaults 提供默认值
const props = withDefaults(defineProps<{isSent?: boolean;iconColor?: string;backgroundColor?: string;smallSize?: number;middleSize?: number;largeSize?: number;duration?: number;audioSrc?: string;}>(),{isSent: false,iconColor: "#000000",backgroundColor: "",smallSize: 10,middleSize: 20,largeSize: 30,duration: 0,audioSrc: ""}
);const isPlaying = ref(false);
let audio: HTMLAudioElement | null = null;// 计算动态样式
const smallStyle = computed(() => ({color: props.iconColor,width: `${props.smallSize}px`,height: `${props.smallSize}px`,marginRight: -props.smallSize + "px"
}));const middleStyle = computed(() => ({color: props.iconColor,width: `${props.middleSize}px`,height: `${props.middleSize}px`,marginRight: -props.middleSize + "px"
}));const largeStyle = computed(() => ({color: props.iconColor,width: `${props.largeSize}px`,height: `${props.largeSize}px`,marginRight: "1px"
}));// 切换播放状态的函数
const togglePlayback = () => {if (isPlaying.value) {pauseVoice();} else {playVoice(props.audioSrc || "");}
};// 播放音频的函数
const playVoice = (voiceSrc: string) => {if (!voiceSrc) {console.error("音频源不能为空");return;}// 如果音频上下文不存在,则创建新的 HTMLAudioElementif (!audio) {audio = new Audio(voiceSrc);} else {audio.src = voiceSrc;}isPlaying.value = true;// 播放音频audio.play().catch(error => console.error("音频播放失败", error));// 监听播放结束事件audio.onended = () => {isPlaying.value = false;};
};// 暂停音频的函数
const pauseVoice = () => {isPlaying.value = false;if (audio) {audio.pause();}
};// 组件卸载时销毁音频上下文
onBeforeUnmount(() => {if (audio) {audio.pause();audio = null;}
});defineExpose({pauseVoice
});
</script><style scoped>
.voice-message {display: inline-flex;align-items: center;cursor: pointer;border-radius: 10px;padding: 4px 12px;
}.voice-message.sent {justify-content: flex-end;
}.voice-message.received {justify-content: flex-start;
}.voice-icon {display: flex;align-items: center;
}.voice-icon.sent-icon {transform: rotate(180deg);
}.small,
.middle,
.large {border-style: solid;border-top-color: transparent;border-left-color: transparent;border-bottom-color: transparent;border-radius: 50%;box-sizing: border-box;vertical-align: middle;display: inline-block;background-color: transparent; /* 默认背景颜色为透明 */
}.middle.animate {animation: show2 3s ease-in-out infinite;
}.large.animate {animation: show3 3s ease-in-out infinite;
}@keyframes show2 {0% {opacity: 0;}30% {opacity: 1;}100% {opacity: 0;}
}@keyframes show3 {0% {opacity: 0;}60% {opacity: 1;}100% {opacity: 0;}
}.duration {margin-left: 8px;font-size: 20px;color: #ffffff;font-weight: 400;
}
</style>

使用时:

<VoicePlayback:isSent="false"iconColor="#ffffff"backgroundColor="rgba(255 255 255 / 20%)":smallSize="5":middleSize="16":largeSize="28":duration="30"audioSrc="http://music.163.com/song/media/outer/url?id=447925558.mp3"
/>

http://www.lryc.cn/news/431171.html

相关文章:

  • ES6 reduce方法详解:示例、应用场景与实用技巧
  • java后端保存的本地图片通过ip+端口直接访问
  • 2024 年高教社杯全国大学生数学建模竞赛B题4小问解题思路(第二版)
  • docker-nginx数据卷挂载
  • 项目实战 ---- 商用落地视频搜索系统(8)---优化(2)---查询逻辑层优化
  • 山东大学机试试题合集
  • 餐厅食品留样管理系统小程序的设计
  • 亚马逊运营:如何提高亚马逊销量和运营效率?
  • 设计模式背后的设计原则和思想
  • 项目总体框架
  • k8s Prometheus
  • glsl着色器学习(九)屏幕像素空间和设置颜色
  • 前端框架有哪些?
  • 分类预测|基于黑翅鸢优化轻量级梯度提升机算法数据预测Matlab程序BKA-LightGBM多特征输入多类别输出 含对比
  • 利用大模型实时提取和检索多模态数据探索-利用 Indexify 进行文档分析
  • 函数式接口实现策略模式
  • 鸿蒙Next-拉起支付宝的三种方式——教程
  • Vue.js 组件化开发:父子组件通信与组件注册详解
  • 【HTTP、Web常用协议等等】前端八股文面试题
  • Datawhale x李宏毅苹果书AI夏令营深度学习详解进阶Task03
  • 【机器学习】任务三:基于逻辑回归与线性回归的鸢尾花分类与波士顿房价预测分析
  • 【操作系统存储篇】Linux文件基本操作
  • C++ | Leetcode C++题解之第387题字符串中的第一个唯一字符
  • 数学建模--皮尔逊相关系数、斯皮尔曼相关系数
  • DAY87 APP 攻防-安卓逆向篇Smail 语法反编译签名重打包Activity 周期Hook 模块
  • jenkins 工具使用
  • 使用C语言实现字符推箱子游戏
  • 用SpringBoot API实现识别pdf文件是否含有表格
  • 嵌入式S3C2440:控制LED灯
  • 算法:区间dp