h5+css3语音实时聊天系统|仿微信语音聊天|js音频录制|仿微信地图定位
基于html5开发的仿微信语音聊天系统weChatIM项目,采用了h5+css3+jQuery+swiper+wcPop+mescroll等技术选型开发,实现了下拉刷新消息,发送信息、表情,预览大图、视频,红包、语音、地图定位等新增功能。
/*
* 下拉刷新、上拉加载更多演示demo
*/
//创建MeScroll对象
var mescroll = new MeScroll("mescroll", {
// 上拉刷新配置
down : {
auto : true, //是否在初始化完毕之后自动执行下拉回调callback; 默认true
callback : downCallback, //下拉刷新的回调
textInOffset : '下拉刷新',
textOutOffset : '释放立即刷新',
textLoading : '正在刷新...'
},
// 下拉加载配置
up: {
auto: true, //是否在初始化时以上拉加载的方式自动加载第一页数据; 默认false
isBounce: false, //此处禁止ios回弹,解析(务必认真阅读,特别是最后一点): http://www.mescroll.com/qa.html#q10
callback: upCallback, //上拉回调,此处可简写; 相当于 callback: function (page) { upCallback(page); }
}
});
/*下拉刷新的回调 */
function downCallback() {
//联网加载数据
getListDataFromNet(0, 1, function (data) {
mescroll.endSuccess();
//设置列表数据
setListData(data, false);
}, function () {
mescroll.endErr();
});
}
/*上拉加载的回调 page = {num:1, size:10}; num:当前页 从1开始, size:每页数据条数 */
function upCallback(page) {
//联网加载数据
getListDataFromNet(page.num, page.size, function (curPageData) {
//联网成功的回调,隐藏下拉刷新和上拉加载的状态;
mescroll.endSuccess(curPageData.length);
//设置列表数据
setListData(curPageData, true);
}, function () {
//联网失败的回调,隐藏下拉刷新和上拉加载的状态;
mescroll.endErr();
});
}
/*设置列表数据*/
function setListData(curPageData, isAppend) {
var listDom = document.getElementById("newsList");
for (var i = 0; i < curPageData.length; i++) {
var newObj = curPageData[i];
var str = '' + newObj.title + '
';
str += '' + newObj.content + '
';
var liDom = document.createElement("li");
liDom.innerHTML = str;
if (isAppend) {
listDom.appendChild(liDom); //加在列表的后面,上拉加载
} else {
listDom.insertBefore(liDom, listDom.firstChild); //加在列表的前面,下拉刷新
}
}
}
var downIndex = 0;
function getListDataFromNet(pageNum, pageSize, successCallback, errorCallback) {
//延时一秒,模拟联网
setTimeout(function () {
try {
var newArr = [];
if (pageNum == 0) {
//此处模拟下拉刷新返回的数据
...ajax
} else {
//此处模拟上拉加载返回的数据
...ajax
}
//联网成功的回调
successCallback && successCallback(newArr);
} catch (e) {
//联网失败的回调
errorCallback && errorCallback();
}
}, 1000)
}
// >>> 【按住说话核心模块】------------------------------------------
// ...按住说话
var _voiceObj = $(".J__wdtVoice"), eY1 = 0, eY2 = 0, eY3 = 0, isDrag = true;
var voiceIdx;
var difftime = 0;
function initVoice(){
_voiceObj.on("touchstart", function(e){
difftime = new Date();
if(!isDrag) return;
isDrag = false;
eY1 = e.originalEvent.targetTouches[0].pageY;
_voiceObj.text("松开 结束");
// 弹窗提示
voiceIdx = wcPop({
id: 'wdtVoice',
skin: 'toast',
content: '手指上滑,取消发送',
style: 'border-radius:6px;height: 160px; width:160px;',
time: 10,
opacity: 0,
});
_voiceObj.on("touchmove", function (e) {
e.preventDefault();
eY3 = e.originalEvent.targetTouches[0].pageY;
if(eY1 - eY3 < 150){
_voiceObj.text("松开 结束");
}else{
_voiceObj.text("松开手指,取消发送");
// 弹窗提示
$("#wdtVoice .popui__panel-cnt").html('松开手指,取消发送');
}
});
});
_voiceObj.on("touchend", function (e) {
e.preventDefault();
eY2 = e.originalEvent.changedTouches[0].pageY;
_voiceObj.text("按住 说话");
// 录音时间太短提示
if(new Date() - difftime < 1000){
// 弹窗提示
$("#wdtVoice .popui__panel-cnt").html('录音时间太短!');
} else{
if (eY1 - eY2 < 150) {
// 发送成功
submitData();
console.log("测试数据");
} else {
// 取消发送
console.log("cancel");
}
}
// 关闭弹窗
setTimeout(function(){
wcPop.close(voiceIdx);
}, 500);
isDrag = true;
});
}
// ...获取语音时长
getVoiceTime();
function getVoiceTime(){
$("#J__chatMsgList li .audio").each(function () {
var that = $(this), audio = that.find("audio")[0], duration;
audio.load();
audio.oncanplay = function(){
duration = Math.ceil(audio.duration);
if (duration == 'Infinity') {
getVoiceTime();
} else {
that.find(".time").text(duration + `''`);
that.attr("data-time", duration);
// 语音宽度%
var percent = (duration / 60).toFixed(2) * 100 + 20 + '%';
that.css("width", percent);
}
}
});
}
// ...语音播放事件
var timer = null;
$("body").on("click", "#J__chatMsgList li .audio", function () {
var that = $(this);
that.parents("li").siblings("li").find(".ico_voice").removeClass("active");
that.find(".redot").addClass("off");
// audio播放事件
timer && clearTimeout(timer);
that.parents("li").siblings("li").find("audio")[0].pause();
var audio = that.find("audio")[0], time = that.attr("data-time");
if(audio.paused){
audio.play();
that.find(".ico_voice").addClass("active");
timer = setTimeout(function(){
that.find(".ico_voice").removeClass("active");
}, time*1000);
}else{
audio.pause();
that.find(".ico_voice").removeClass("active");
clearTimeout(timer);
}
});
// 摇一摇功能模块
$("#J__popScreen_shake").on("click", function () {
var shakePopIdx = wcPop({
id: 'wcim_shake_fullscreen',
skin: 'fullscreen',
title: '摇一摇',
content: $("#J__popupTmpl-shakeFriends").html(),
position: 'right',
xclose: true,
style: 'background: #303030;',
show: function(){
// 摇一摇功能
var _shake = new Shake({threshold: 15});
_shake.start();
window.addEventListener("shake", function(){
window.navigator.vibrate && navigator.vibrate(500);
// console.log("触发摇一摇!");
$(".J__shakeInfoBox").html("");
$(".J__shakeLoading").fadeIn(300);
// 消息模板
var shakeTpl = [
'\
\
\
大幂幂
\
\
\
'
].join("");
setTimeout(function(){
$(".J__shakeLoading").fadeOut(300);
$(".J__shakeInfoBox").html(shakeTpl);
}, 1500);
}, false);
}
});
});
$("#J__topbarAdd").on("click", function(e){
var _points = [e.clientX, e.clientY];
var contextMenuIdx = wcPop({
skin: 'contextmenu', shade: true,shadeClose: true,opacity: 0,follow: _points,
style: 'background:#3d3f4e; min-width:3.5rem;',
btns: [
{text: '添加好友',style: 'color:#fff;', onTap(){
wcPop.close(contextMenuIdx);
// 添加好友
var addfriendIdx = wcPop({
id: 'wcim_fullscreen',
skin: 'fullscreen',
title: '添加好友',
content: $("#J__popupTmpl-addFriends").html(),
position: 'right',
opacity: .1,
xclose: true,
style: 'background: #f2f1f6;'
});
}},
{text: '发起群聊',style: 'color:#fff;', onTap(){
wcPop.close(contextMenuIdx);
// 发起群聊
var addfriendIdx = wcPop({
id: 'wcim_fullscreen',
skin: 'fullscreen',
title: '发起群聊',
content: $("#J__popupTmpl-launchGroupChat").html(),
position: 'right',
opacity: .1,
xclose: true,
style: 'background: #f2f1f6;'
});
}},
{text: '帮助与反馈',style: 'color:#fff;',}
]
});
});