乐趣区

h5聊天IM实例仿微信语音地图定位摇一摇效果

前言

相信大家都有使用过微信,微信这款产品确实设计的不错,简约不简单。尤其里面的摇一摇、语音功能更是吸引了大批用户,颠覆式的功能及设计,让微信稳稳坐上了社交宝座。

介绍

之前由于项目需求有开发过一款简单的聊天项目,不过功能及 UI 比较简单,最近又重新在原先的基础上进行了一次大的重构,开发了这款仿微信界面聊天 IM 系统——趣聊 weChatIM。

技术架构 / 功能

基于 html5+css3+Zepto+swiper+wcPop+flex 等技术混合开发,实现了发送消息、表情 (动图),图片、视频预览,添加好友 / 群聊,右键长按菜单。另外新增了语音模块、地图定位模块。整体功能界面效果比较接近微信聊天。

介绍了这么多,一睹效果吧:

怎么样,看了效果图,是不是感觉还不错,棒棒哒。

引入 css 及 js 插件如下:

另外项目中使用的弹窗 wcPop.js,是自己开发的移动端弹窗组件,兼容所有移动设备(亲测),多种 api 调用方式及动画效果;



嗯,效果统一,的确不错。

摇一摇功能,基于 shake.js 插件

$("#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("触发摇一摇!");

                //... 逻辑代码
                
                setTimeout(function(){$(".J__shakeLoading").fadeOut(300);
                    $(".J__shakeInfoBox").html(shakeTpl);
                }, 1500);
            }, false);
        }
    });
});

聊天模块代码片段

// ... 滚动聊天区底部
function wchat_ToBottom() {$(".mescroll").animate({scrollTop: $("#J__chatMsgList").height()}, 0);
}
// ... 处理编辑器信息
var $editor = $(".J__wdtEditor"), _editor = $editor[0];
function surrounds() {setTimeout(function () { //chrome
        var sel = window.getSelection();
        var anchorNode = sel.anchorNode;
        if (!anchorNode) return;
        if (sel.anchorNode === _editor ||
            (sel.anchorNode.nodeType === 3 && sel.anchorNode.parentNode === _editor)) {var range = sel.getRangeAt(0);
            var p = document.createElement("p");
            range.surroundContents(p);
            range.selectNodeContents(p);
            range.insertNode(document.createElement("br")); //chrome
            sel.collapse(p, 0);

            (function clearBr() {var elems = [].slice.call(_editor.children);
                for (var i = 0, len = elems.length; i < len; i++) {var el = elems[i];
                    if (el.tagName.toLowerCase() == "br") {_editor.removeChild(el);
                    }
                }
                elems.length = 0;
            })();}
    }, 10);
}

编辑器框插入表情处理

if (that.hasClass("face")) { // 小表情
    var img = that[0].cloneNode(true);
    if (!_editor.childNodes.length) {_editor.focus();
    }
    _editor.blur(); // 输入表情时禁止输入法

    setTimeout(function () {if (document.selection && document.selection.createRange) {document.selection.createRange().pasteHTML(img);
        } else if (window.getSelection && window.getSelection().getRangeAt) {range = _rng.getRange();
            range.insertNode(img);
            range.collapse(false);

            _lastRange = range; // 记录当前光标位置 (否则光标会跑到表情前面)
            _rng.addRange();}
    }, 10);
}

判断编辑器内容是否为空

function isEmpty() {var html = $editor.html();
    html = html.replace(/<br[\s\/]{0,2}>/ig, "\r\n");
    html = html.replace(/<[^img].*?>/ig, "");
    html = html.replace(/&nbsp;/ig, "");
    return html.replace(/\r\n|\n|\r/, "").replace(/(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g,"") == "";
}

地图模块,采用的是百度地图 api

// ... 选择位置
var poiPopIdx;
$(".J__chooseWz").on("click", function () {
    poiPopIdx = wcPop({
        id: 'wcim_local_fullscreen',
        title: '位置',
        skin: 'fullscreen',
        content: $("#J__popupTmpl-location").html(),
        position: 'right',
        xclose: true,
        style: 'background: #f3f3f3;',
        // 加载地图
        show: function () {$(".J__sendLatlng").show();
            $(".localMap").html('<iframe id="mapPage"width="100%"height="100%"frameborder=0 src="https://apis.map.qq.com/tools/locpicker?search=1&type=1&key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77&referer=myapp"></iframe>');
        }
    });
});
// ... 获取位置坐标点
var pointArr;
window.addEventListener('message', function (event) {
    // 接收位置信息,用户选择确认位置点后选点组件会触发该事件,回传用户的位置信息
    var loc = event.data;
    // 防止其他应用也会向该页面 post 信息,需判断 module 是否为 'locationPicker'
    if (loc && loc.module == 'locationPicker') {console.log('location', loc);
        pointArr = loc;
    }
}, false);
退出移动版