小程序聊天室|聊天对话小程序|仿微信界面

微信小程序开发的仿微信聊天室weChatRoom项目|聊天小程序demo实例

基于微信小程序开发的聊天室实战案例。很早之前就有开发过一个h5版聊天室,最近又开发了个小程序版聊天室,功能效果非常接近微信聊天,实现了消息、表情发送,小程序表情解析,图片、视频上传预览,打赏、红包等功能。

// pages/groupChat/groupChat.js

var util = require('../../utils/util.js');

import { wcPop } from '../../utils/component/wcPop/tpl.js';

const emotions = require('./emotion-mock-data.js');
const messages = require('./chat.mock-data.js');
var emojParse = require('./emojParse.js');

Page({

  /**
   * 页面的初始数据
   */
  data: {
    cursorSpacing: 15, //光标与键盘的距离
    toView: "scrollBottom", //定位到聊天底部
    isEditorFocus: false, //编辑器获取焦点
    isEditorPreview: false, //编辑器消息预览

    // 消息记录
    __messages: messages,

    // 表情集合
    __emotions: emotions.list,

    // 预览图片地址
    previewImgList: [],


  },

  onLaunch: function(){
    // ...
  },

  onLoad: function () {
    // 初始化解析表情
    emojParse.init(this, ":_/");

    // 解析消息记录里面的表情符号
    var _messages = this.data.__messages;
    for (var i = 0, len = _messages.length; i < len; i++) {
      // 解析含表情的消息
      if (_messages[i].msgtype == 3){
        // 解析消息记录表情字符串
        _messages[i].msg = { emojiTextArray: emojParse.transEmojStr(_messages[i].msg)};
      }
    }
    this.setData({
      __messages: _messages
    });
  },


  /**
   * 聊天页面JS功能模块-------------------------------------------------
  */
  // 滚动聊天底部
  bindToMsgBottom: function (e) {
    var that = this;
    setTimeout(function(){that.setData({ toView: "scrollBottom" });}, e ? 100 : 0);
  },

  // 点击聊天面板区域
  bindTapMsgPanel: function (e) {
    this.setData({ isShowChoosePanel: false });
  },

  // 表情/选择区切换
  bindSwtEmotion: function (e) {
    var that = this;
    this.setData({
      isShowChoosePanel: true, isShowEmotion: true, isShowChoose: false,
    });
    // 滚动到聊天底部
    this.bindToMsgBottom();
  },
  bindSwtChoose: function (e) {
    var that = this;
    this.setData({
      isShowChoosePanel: true, isShowEmotion: false, isShowChoose: true,
    });
    // 滚动到聊天底部
    this.bindToMsgBottom();
  },
  // 底部多表情切换
  bindSwtEmotionBar: function(e) {
    var idx = e.currentTarget.dataset.index;
    var _lists = this.data.__emotions;
    for (var i = 0, len = _lists.length; i < len; i++){
      _lists[i].selected = false;
    }
    _lists[idx].selected = true;
    this.setData({ __emotions: _lists });
  },

  // 点击大图
  bindGifImageTap: function (e) {
    wx.showLoading({title: '发送中...',});

    var that = this;
    var _messages = this.data.__messages;
    var _len = _messages.length;
    var gifpath = e.currentTarget.dataset.path;

    // 消息队列
    var _data = {
      id: `msg${++_len}`,
      msgtype: 6, //大表情
      isme: true,
      avatar: "../../img/uimg/u__chat-img14.jpg",
      author: "Nice奈斯",
      msg: "",
      imgsrc: gifpath,
      videosrc: ""
    };
    _messages = _messages.concat(_data);
    this.setData({ __messages: _messages });
    setTimeout(function () { wx.hideLoading(); }, 100);

    // 滚动到聊天底部
    this.bindToMsgBottom(true);
  },

  // 选择图片
  bindChooseImage: function (e) {
    var that = this;
    var _messages = this.data.__messages;
    var _len = _messages.length;

    // 消息队列
    var _data = {
      id: `msg${++_len}`,
      msgtype: 4, //发送图片
      isme: true,
      avatar: "../../img/uimg/u__chat-img14.jpg",
      author: "Nice奈斯",
      msg: "",
      imgsrc: "",
      videosrc: ""
    };

    wx.chooseImage({
      count: 1,
      success: function(res) {
        // console.log(res);
        // console.log(res.tempFilePaths);

        _data.imgsrc = res.tempFilePaths.toString(); //把单张数组格式图片转换为字符串格式
        _messages = _messages.concat(_data);
        that.setData({ __messages: _messages });

        // 滚动到聊天底部
        that.bindToMsgBottom(true);
      },
    })
  },

  // 预览图片
  bindPreviewImage: function (e) {
    // 遍历所有当前聊天记录图片
    var _src = e.currentTarget.dataset.src;
    var _messages = this.data.__messages;
    var _imglist = this.data.previewImgList;
    for (var i = 0, len = _messages.length; i < len; i++) {
      if (_messages[i].imgsrc != "" && _messages[i].msgtype == 4) {
        if (_imglist.indexOf(_messages[i].imgsrc) == -1) {
          _imglist.push(_messages[i].imgsrc);
        }
      }
    }
    // preview images
    wx.previewImage({
      current: _src,
      urls: _imglist,
    })
  },

  // 预览视频
  bindPreviewVideo: function (e) {
    var _id = e.currentTarget.dataset.id;
    this.playContext = wx.createVideoContext("video_" + _id, this);

    this.playContext.play();
    this.playContext.requestFullScreen({ direction: 0 });
  },
  // 全屏事件
  bindFullscreenchange: function (e) {
    var _id = e.currentTarget.dataset.id;
    this.fullchangeContext = wx.createVideoContext("video_" + _id, this);

    if (e.detail.fullscreen == false){
      this.fullchangeContext.pause();
      this.fullchangeContext.exitFullScreen();
    }
  },
  // 视频播放结束
  bindEndedVideo: function (e) {
    var _id = e.currentTarget.dataset.id;
    this.stopContext = wx.createVideoContext("video_" + _id, this);

    this.stopContext.stop();
    this.stopContext.exitFullScreen();
  },

  // 打赏
  bindDashang: function (e) {
    var dsIdx = wcPop({
      skin: 'android',
      content: ['wc__tmpl_dashang'],
      xclose: true,
      shadeClose: false,
      style: 'background: #f3f3f3;',
    });
  },

  // 发送红包
  bindHongbao: function (e) {
    var hbIdx = wcPop({
      skin: 'android',
      content: ['wc__tmpl_hongbao'],
      xclose: true,
      shadeClose: false,
      style: 'background: #f3f3f3;',
    });
  },


})
<!-- 表情区域 -->
<view class="wrap-emotion" style="display:{{isShowEmotion ? 'block' : 'none'}};">
  <view class="emotion__cells flexbox flex__direction-column">
	<!-- //表情swiper -->
	<block wx:for="{{__emotions}}" wx:key="index" wx:for-item="item">
	<view class="emotion__cells-swiper flex1 {{item.selected ? 'cur' : ''}}">
	  <swiper indicator-dots="true" duration="200">
		<block wx:for="{{item.lists}}" wx:key="*item" wx:for-item="item2">
		  <swiper-item class="{{item.type}}">
			<view class="item">
			  <block wx:for="{{item2.nodes}}" wx:key="*item2" wx:for-item="item3">
				<label wx:if="{{item.type == 'face__sm-list'}}" bindtap="bindEmotionTap" data-emot=":{{item3}}:">
				  <image wx:if="{{item3 == 'del'}}" src="../../img/wchat/icon__emotion-del.png"></image>
				  <image wx:else src="{{item.path}}/{{item3}}.gif"></image>
				</label>
				<!-- 大表情 -->
				<label wx:if="{{item.type == 'face__lg-list'}}" bindtap="bindGifImageTap" data-path="{{item.path}}/{{item3}}.gif">
				  <image wx:if="{{item3 == 'del'}}" src="../../img/wchat/icon__emotion-del.png"></image>
				  <image wx:else src="{{item.path}}/{{item3}}.gif"></image>
				</label>
			  </block>
			</view>
		  </swiper-item>
		</block>
	  </swiper>
	</view>
	</block>
	<!-- //底部表情栏 -->
	<view class="emotion__cells-footer wc__borT">
	  <scroll-view class="ul" scroll-x>
		<block wx:for="{{__emotions}}" wx:key="index">
		<view class="li {{item.selected ? 'cur' : ''}}" data-index="{{index}}" bindtap="bindSwtEmotionBar"><image src="{{item.path}}/face-lbl.gif"></image></view>
		</block>
		<view class="li"><image src="../../img/wchat/icon__emotion-set.png"></image></view>
	  </scroll-view>
	</view>
  </view>
</view>

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券