微信小程序利用腾讯云IM发送语音 + 图片
能做到这里 说明你已经可以发送普通文本了 如果没有的话可以看一下我的上一篇文章 有完整的讲解
效果图
![]() |
![]() |
传送 → 发送图片
发送语音
**
1,页面wxml
<!-- 音频 -->
<block wx:if="{{item.type == 'TIMSoundElem'}}">
<!-- 默认状态 -->
<view class='content' wx:if="{{isplayId != item.payload.uuid || !isplayId}}" bindtap='audioPlay' data-key="{{index}}" data-id="{{item.payload.uuid}}" data-src="{{item.payload.url}}">
<view class='audio' style="width:calc(90rpx + {{item.payload.second*10}}rpx);max-width: 464rpx">
<image class='ico' mode="widthFix" src='/images/record_icon2.png' />
<label class='time'>{{item.payload.second}}''</label>
</view>
</view>
<!-- 当前正在播放状态 -->
<view class='content' wx:if="{{isplayId == item.payload.uuid}}">
<view class='audio' style="width:calc(90rpx + {{item.payload.second*10}}rpx);max-width: 464rpx">
<image class='ico' mode="widthFix" src='/images/record_icon3.gif' />
<label class='time'>{{item.payload.second}}''</label>
</view>
</view>
</block>
<!-- 录音时的提示 -->
<view wx:if="{{isRecording}}" class="record-modal">
<view class="wrapper">
<image src="/images/record_icon1.png" mode="widthFix" class="icon1"></image>
<image src="/images/record_icon.gif" mode="widthFix" class="modal-loading"></image>
</view>
<view class="modal-title">
{{title}}
</view>
</view>
2,wxss样式
/* 录音 */
.record-modal {
height: 230rpx;
width: 260rpx;
background-color: rgba(0, 0, 0, 0.8);
position: fixed;
top: 163rpx;
right: 0;
left: 0;
margin: auto;
border-radius: 14px;
display: flex;
flex-direction: column;
}
.wrapper {
display: flex;
box-sizing: border-box;
padding: 47rpx 60rpx 26rpx 60rpx;
align-items: center;
justify-content: space-between;
}
.icon1{
width: 55rpx;
}
.modal-loading{
width: 58rpx;
height: 48rpx;
}
.modal-title{
text-align:center;
color: white;
font-size: 26rpx;
}
.audio{
height: 100%;
display: flex;
align-items: center;
flex-direction: row-reverse;
}
.ico{
width: 24rpx;
height: 33rpx;
}
.time{
font-size: 28rpx;
color: #232323;
margin-right: 18rpx;
}
3,js,相关逻辑(点击键盘变语音 长按录音 上滑取消 播放)
//创建audio控件
const myaudio = wx.createInnerAudioContext()
onLoad:function() {
recorderManager.onStart(() => {
console.log('recorder start')
})
recorderManager.onPause(() => {
console.log('recorder pause')
})
recorderManager.onStop((res) => {
console.log('recorder stop')
console.log(res)
wx.hideLoading()
if (that.data.canSend) {
if (res.duration < 1000) {
wx.showToast({
title: '录音时间太短',
icon: "none"
})
} else {
// 4. 创建消息实例,接口返回的实例可以上屏
var tim = app.globalData.tim
console.log(tim)
const message = tim.createAudioMessage({
to: that.data.conversationID.slice(3), // 消息的接收方
conversationType: TIM.TYPES.CONV_C2C,
payload: {
file: res
}
});
that.sendMessageFun(message)
}
}
})
}
// 点击录音
record(e) {
this.setData({
isrecord: !this.data.isrecord
})
},
// 长按事件
handleRecordStart(e) {
var that = this
that.setData({
startPoint: e.touches[0],
title: '正在录音',
isRecording: true,
canSend: true,
title_input: '抬起 停止'
})
that.startRecording()
},
// 录音时的手势上划移动距离对应文案变化
handleTouchmove(e) {
var that = this
var isRecording = that.data.isRecording
var startPoint = that.data.startPoint
if (isRecording) {
if (startPoint.clientY - e.touches[e.touches.length - 1].clientY > 100) {
that.setData({
title: '松开手指,取消发送',
canSend: false
})
} else if (startPoint.clientY - e.touches[e.touches.length - 1].clientY > 20) {
that.setData({
title: '上划可取消',
canSend: true
})
} else {
that.setData({
title: '正在录音',
canSend: true
})
}
}
},
// 手指离开页面滑动
handleRecordStop(e) {
this.setData({
isRecording: false
})
wx.hideLoading()
recorderManager.stop()
},
// 开始录音之前要判断一下是否开启权限
startRecording () {
wx.getSetting({
success: (res) => {
let auth = res.authSetting['scope.record']
if (auth === false) { // 已申请过授权,但是用户拒绝
wx.openSetting({
success: function (res) {
let auth = res.authSetting['scope.record']
if (auth === true) {
wx.showToast({
title: '授权成功',
icon: 'success',
duration: 1500
})
} else {
wx.showToast({
title: '授权失败',
icon: 'none',
duration: 1500
})
}
}
})
} else if (auth === true) { // 用户已经同意授权
this.setData({
isRecording: true
})
recorderManager.start(this.data.recordOptions)
} else { // 第一次进来,未发起授权
wx.authorize({
scope: 'scope.record',
success: () => {
wx.showToast({
title: '授权成功',
icon: 'success',
duration: 1500
})
}
})
}
},
fail: function () {
wx.showToast({
title: '授权失败',
icon: 'none',
duration: 1500
})
}
})
},
//音频播放
audioPlay: function (e) {
var that = this
var id = e.currentTarget.dataset.id // 要播放的音频的id
var key = e.currentTarget.dataset.key // 索引
var src = e.currentTarget.dataset.src //要播放的音频
myaudio.src = src
myaudio.autoplay = true
//切换显示状态
this.setData({
isplayId: id
})
myaudio.play()
//开始监听
myaudio.onPlay(() => {
console.log('监听播放的回调函数')
})
//结束监听
myaudio.onEnded(() => {
that.setData({
isplayId: ''
})
})
},
4,页面用到的变量(写在最后 图片和音频)
5,这里面用到的sendMessageFun跟之前发送消息的函数是一样的 做了封装 看→
发送图片
1,页面wxml展示
<!-- 图片 -->
<block wx:if="{{item.type == 'TIMImageElem'}}">
<image wx:if="{{!item.send}}" class="msg_pic" style="width:100%;" mode="widthFix" bindload="outputSrc" lazy-load="{{true}}" src="{{item.payload.imageInfoArray[0].url}}" bindtap="previewImage" data-url="{{item.payload.imageInfoArray[2].url}}"></image>
<image wx:else class="msg_pic" style="width:100%;" mode="widthFix" bindload="outputSrc" lazy-load="{{true}}" src="{{item.sendPic}}" bindtap="previewImage" data-url="{{item.payload.imageInfoArray[2].url}}">
<view class="progress">{{percent * 100}}%</view>
</image>
</block>
<!-- 底部样式做了修改 -->
<view class="chat-footer" style="padding-bottom: calc({{tabBottom}}px + 25rpx)">
<view class="chat_input_box">
<image wx:if="{{isrecord}}" src="/images/msg_record.png" mode="widthFix" class="msg_icon" style="margin-right: 25rpx;" bindtap="record"></image>
<image wx:else src="/images/msg_key.png" mode="widthFix" class="msg_icon" style="margin-right: 25rpx;" bindtap="record"></image>
<view class='input' bindtap="bindFocus" wx:if="{{isrecord}}">
<input class="inputArea" focus="{{focus}}" cursor-spacing="25" bindinput="bindKeyInput" bindfocus="bindfocus" bindblur="bindblur" value="{{inputValue}}" placeholder=""/>
<text class="placeHolder" wx:if="{{inputShow}}">对ta发送消息</text>
</view>
<view wx:else class="speak" bindtap="getrecord" bindlongpress="handleRecordStart" bindtouchmove="handleTouchmove" bindtouchend="handleRecordStop">{{title_input}}</view>
<image src="/images/msg_more.png" mode="widthFix" class="msg_icon" style="margin-left: 25rpx;" bindtap="moreClick"></image>
<view class='send' bindtap='bindConfirm'>发送</view>
</view>
<view class="open_more" wx:if="{{sendPic}}">
<view class="open_more_item" bindtap="sendPhoto" data-name="album">
<image src="/images/msg_img.png" mode="widthFix" class="msg_img"></image>
<view class="msg_text">相册</view>
</view>
<view class="open_more_item" bindtap="sendPhoto" data-name="camera">
<image src="/images/msg_photo.png" class="msg_img" mode="widthFix"></image>
<view class="msg_text">拍摄</view>
</view>
</view>
</view>
2,wxss页面样式(修改了之前底部的样式)
/* 图片消息 */
.imgbox{
width: 100%;
height: 100%;
display: flex;
flex-direction: row-reverse;
}
.msg_pic {
max-width: 256rpx;
background-image: url(https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1588859561060&di=0528a9f22beb9a4b5f443c16bbf3b5e0&imgtype=0&src=http%3A%2F%2Fhbimg.b0.upaiyun.com%2Fa72000f4a3780806d4039168bd98ad1f16ea94be73d6-qBWrxA_fw658);
background-repeat: no-repeat;
background-size: center;
background-position: center;
border-radius: 4rpx;
position: relative;
}
.progress{
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(29, 29, 29, 0.548);
color: #fff;
}
/* 底部样式 */
.chat-footer{
position: fixed;
bottom: 0;
left: 0;
width: 100%;
background:rgba(248,248,248,1);
box-shadow:0px -1px 0px 0px rgba(221,221,221,1);
padding: 20rpx 25rpx;
}
.chat_input_box{
display: flex;
justify-content: space-between;
align-items: center;
}
.msg_icon{
width: 58rpx;
height: 58rpx;
}
.input{
height:76rpx;
line-height: 76rpx;
background:rgba(255,255,255,1);
border: none;
border:1px solid rgba(212, 215, 222, 1);
border-radius:6rpx;
font-size: 26rpx;
padding:0 20rpx;
display: flex;
flex-direction: row;
align-items: center;
position: relative;
flex-grow: 1;
}
.speak{
height:76rpx;
background:rgba(255,255,255,1);
border:1px solid rgba(212, 215, 222, 1);
border-radius:6rpx;
font-size: 26rpx;
padding:0 20rpx;
display: flex;
justify-content: center;
align-items: center;
flex-grow: 1;
color: #666666;
}
.inputArea{
width: 100%;
height: 98%;
flex-grow: 1;
}
.placeHolder{
position: absolute;
font-size: 26rpx;
color: #cccccc;
height: 100%;
box-sizing: border-box;
top: 0;
z-index: 0;
}
.send{
color: #fff;
background-color: #FF9328;
width: 124rpx;
height: 76rpx;
border-radius: 12rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 26rpx;
margin-left: 20rpx;
}
.footer-h{
position: fixed;
top: 100px;
}
.more{
display: flex;
justify-content: center;
align-items: center;
}
.more_text{
padding: 6rpx 14rpx;
background:rgba(216,216,216,1);
border-radius:4rpx;
color: #FFFFFF;
font-size: 20rpx;
margin: 30rpx auto;
}
3,js(点击三个点 弹出底部选择图片或者拍照)
// 点更多...出现图片和相册
moreClick() {
this.setData({
sendPic: true
})
},
// 点击屏幕 发消息更多的弹框下去
bodyTouch() {
this.setData({
sendPic: false
})
},
// 点击相册
sendPhoto (e) {
var that = this
var name = e.currentTarget.dataset.name
if (name === 'album') {
that.chooseImage(name)
} else if (name === 'camera') {
wx.getSetting({
success: function (res) {
if (!res.authSetting['scope.camera']) { // 无权限,跳转设置权限页面
wx.authorize({
scope: 'scope.camera',
success: function () {
that.chooseImage(name)
}
})
} else {
that.chooseImage(name)
}
}
})
}
},
// 选择图片
chooseImage (name) {
var that = this
var tim = app.globalData.tim
wx.chooseImage({
sourceType: [name],
count: 1,
success: function (res) {
// debugger
console.log(res)
// 在发送之前先push进去一张图片
var messageList = that.data.myMessages
var data = {
type: 'TIMImageElem',
send: true,
sendPic: res.tempFilePaths[0]
}
messageList.push(data)
that.setData({
myMessages: messageList
})
// 2. 创建消息实例,接口返回的实例可以上屏
let message = tim.createImageMessage({
to: that.data.conversationID.slice(3), // 消息的接收方,
conversationType: TIM.TYPES.CONV_C2C,
payload: { file: res },
onProgress: function(event) {
console.log('file uploading:', event)
that.setData({
percent: event
})
}
})
that.sendMessageFun(message, 'pic')
}
})
// that.handleClose()
},
// 预览
previewImage(e) {
var url = e.currentTarget.dataset.url
wx.previewImage({
current: url, // 当前显示图片的http链接
urls: [url]
})
},
相关变量
data: {
isrecord: true,
// 录音部分参数
recordOptions: {
duration: 60000, // 录音的时长,单位 ms,最大值 600000(10 分钟)
sampleRate: 44100, // 采样率
numberOfChannels: 1, // 录音通道数
encodeBitRate: 192000, // 编码码率
format: 'aac' // 音频格式,选择此格式创建的音频消息,可以在即时通信 IM 全平台(Android、iOS、微信小程序和 Web)互通
},
title: '正在录音',
isRecording: false,
canSend: true,
isplayId: '',
title_input: '按住 说话',
sendPic: false,
percent: 0
}
sendMessageFun函数的封装
![]() |
|
sendMessageFun(message,type) {
var tim = app.globalData.tim
var that = this
// 2. 发送消息
let promise = tim.sendMessage(message)
promise.then(function(imResponse) {
// 发送成功
if(type == 'pic') {
var messageList = that.data.myMessages
messageList.pop()
that.setData({
myMessages: messageList
})
}
var messageList = that.data.myMessages
messageList.push(imResponse.data.message)
that.setData({
is_lock:true,
myMessages: messageList,
percent: 0
})
that.pageScrollToBottom()
that.clearInput()
}).catch(function(imError) {
// 发送失败
console.warn('sendMessage error:', imError);
})
}
差不多到这儿就完事儿啦(≧▽≦)/,发图片有一个问题(¬_¬) , 微信小程序SDK imagePayLoad参数中的sizeType 表示不同压缩比例 但是实际应用中 并没有压缩 也提交工单询问了 最后的回复是 目前暂不支持 所以图片在展示的时候暂时没有做压缩处理
有什么问题可以评论,不足之处 求大神指导。(✪ω✪)