微信小程序利用腾讯云IM发送语音 + 图片

微信小程序利用腾讯云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 表示不同压缩比例 但是实际应用中 并没有压缩 也提交工单询问了 最后的回复是 目前暂不支持 所以图片在展示的时候暂时没有做压缩处理 在这里插入图片描述

有什么问题可以评论,不足之处 求大神指导。(✪ω✪)

  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值