聊天会话常用JS/CSS代码

滑动到列表底部

<div class="chat-dialog-cont"> 
 <ul class="im-chat-ul">
 </ul>
</div>
解决办法一:

一开始就从列表底部加载以避免跳动。查了好久,这个描述最贴切

https://stackoverflow.com/questions/18614301/keep-overflow-div-scrolled-to-bottom-unless-user-scrolls-up

根据上面的描述:

  1. JS 解法和上面的代码差不多,然后定时去调整 : (
  2. CSS 解法 是用 flex-direction: column-reverse; 去旋转列表,但是好像效果不好。。。
$('.chat-dialog-cont').animate({ scrollTop: $('ul.im-chat-ul').prop('scrollHeight') }, 'fast');

判断到顶部的方法是这样的:

 $('.chat-dialog-cont').scroll(() => {
   if (this.hasMoreHistory) {
     if ($('.chat-dialog-cont').scrollTop() === 0) {
       //this._loadMore();
     }
   }
 });
解决办法二:

我在想,要不旋转180度好了,结果真的可以,每次打开直接从底部开始滑动起:),代码大概是这样

.chat-dialog-cont{
	height: 392px;
	overflow-x: hidden;
	overflow-y: auto;
	border-top: 1px solid #D4D4D4;
	transform: rotate(180deg);
	direction:rtl;
	text-align:left;
	ul{
		overflow: hidden;
		transform: rotate(180deg);
	}
}

重要的只有三行代码:transform: rotate(180deg); direction:rtl; text-align:left;

判断到顶部的方法是这样的:

$('.chat-dialog-cont').scroll(() => {
 if (this.hasMoreHistory) {
   let cont = $('.chat-dialog-cont');
   if (cont.height() + cont.scrollTop() === $('ul.im-chat-ul').prop('scrollHeight')) {
     // this._loadMore();
   }
 }
});

第二种方法完美的避免了加载图片之后的跳动

但是…发现好像鼠标的滚动好像有点吊诡。
然后被人发现这个问题了(逃)。
然后鲁大师出手帮我修了,厚着脸皮偷偷贴下他的代码。

可以这样修改鼠标滚轮的方向

$(document).on('mousewheel DOMMouseScroll', function(e) {
    e.preventDefault();
    var value = e.originalEvent.wheelDelta || -e.originalEvent.detail;
    var delta = Math.max(-1, Math.min(1, value));
    var decoration = delta > 0 ? 'Up' : 'down';
    $(document).scrollTop($(document).scrollTop() + 50 * delta);
});

但是edge的浏览器对兼容性提出了质疑(在edge上,列表会变白屏),后来发现是 direction:rtl 的缘故。

找了一下方法,我是这样修的:

@supports not (-ms-ime-align: auto) {.chat-dialog-cont{direction:rtl;}}
@supports (-ms-ime-align: auto) {.chat-dialog-cont{-ms-overflow-style:none;}}

处理聊天列表中表情包层的窗口关闭事件

// display dialog
$('.button').click(function(event) {
  $('.expression-layer').show();
  event.preventDefault();
  return false;
});

// handle close dialog events
function(show) {
  if (!this.nameClick) this.nameClick = function nameClick(event) { $('.expression-layer').hide(); };
  if (show) {
    window.document.body.addEventListener('click', this.nameClick, true);
  } else {
    window.document.body.removeEventListener('click', this.nameClick, true);
  }
}

回车输入文字

方法一:
$('textarea.chat-dialog-inp').keyup(function(event) {
  if (event.keyCode === 13) {
    let content = this.value;
    let caret = getCaret(this);
    if (event.shiftKey) {
      this.value = content.substring(0, caret - 1) + '\n' + content.substring(caret, content.length);
      event.stopPropagation();
    } else {
      this.value = content.substring(0, caret - 1) + content.substring(caret, content.length);
      // self.send();
    }
  }
});

function getCaret(el) {
  if (el.selectionStart) {
    return el.selectionStart;
  } else if (document.selection) {
    el.focus();
    let r = document.selection.createRange();
    if (r == null) {
      return 0;
    }
    let re = el.createTextRange();
    let rc = re.duplicate();
    re.moveToBookmark(r.getBookmark());
    rc.setEndPoint('EndToStart', re);
    return rc.text.length;
  }
  return 0;
}
方法二:
 $('textarea.chat-dialog-inp').keyup(event => {
   // allow sending message when input enter(without shift)
   // refer to : https://stackoverflow.com/questions/6014702/how-do-i-detect-shiftenter-and-generate-a-new-line-in-textarea/6015906#6015906
   if (event.keyCode === 13 && !event.shiftKey) {
     this._sendText();
   }
 });

推荐方法二。

聊天列表把[汗] 这样的表情修改成图片

下面代码来自 NIM_Web_Demo

/**
 * 1. 将 `[汗]` 等默认表情转化为图片
 * 2. 处理回车换行的逻辑
 */
item.showText = escape(item.text);
if (/\[[^\]]+\]/.test(item.showText)) {
  let emojiItems = item.showText.match(/\[[^\]]+\]/g);
  emojiItems.forEach(text => {
    let emojiCnt = emojiList.emoji;
    if (emojiCnt[text]) {
      item.showText = item.showText.replace(text, `<img class="emoji-small" src="${emojiCnt[text].img}">`);
    }
  });
}


let emojiBaseUrl = 'http://yx-web.nosdn.127.net/webdoc/h5/emoji';
let emojiList = {
  'emoji': {
    '[大笑]': { file: 'emoji_0.png' }, '[可爱]': { file: 'emoji_01.png' }, '[色]': { file: 'emoji_02.png' }, '[嘘]': { file: 'emoji_03.png' }, '[亲]': { file: 'emoji_04.png' }, '[呆]': { file: 'emoji_05.png' }, '[口水]': { file: 'emoji_06.png' }, '[汗]': { file: 'emoji_145.png' }, '[呲牙]': { file: 'emoji_07.png' }, '[鬼脸]': { file: 'emoji_08.png' }, '[害羞]': { file: 'emoji_09.png' }, '[偷笑]': { file: 'emoji_10.png' }, '[调皮]': { file: 'emoji_11.png' }, '[可怜]': { file: 'emoji_12.png' }, '[敲]': { file: 'emoji_13.png' }, '[惊讶]': { file: 'emoji_14.png' }, '[流感]': { file: 'emoji_15.png' }, '[委屈]': { file: 'emoji_16.png' }, '[流泪]': { file: 'emoji_17.png' }, '[嚎哭]': { file: 'emoji_18.png' }, '[惊恐]': { file: 'emoji_19.png' }, '[怒]': { file: 'emoji_20.png' }, '[酷]': { file: 'emoji_21.png' }, '[不说]': { file: 'emoji_22.png' }, '[鄙视]': { file: 'emoji_23.png' }, '[阿弥陀佛]': { file: 'emoji_24.png' }, '[奸笑]': { file: 'emoji_25.png' }, '[睡着]': { file: 'emoji_26.png' }, '[口罩]': { file: 'emoji_27.png' }, '[努力]': { file: 'emoji_28.png' }, '[抠鼻孔]': { file: 'emoji_29.png' }, '[疑问]': { file: 'emoji_30.png' }, '[怒骂]': { file: 'emoji_31.png' }, '[晕]': { file: 'emoji_32.png' }, '[呕吐]': { file: 'emoji_33.png' }, '[拜一拜]': { file: 'emoji_160.png' }, '[惊喜]': { file: 'emoji_161.png' }, '[流汗]': { file: 'emoji_162.png' }, '[卖萌]': { file: 'emoji_163.png' }, '[默契眨眼]': { file: 'emoji_164.png' }, '[烧香拜佛]': { file: 'emoji_165.png' }, '[晚安]': { file: 'emoji_166.png' }, '[强]': { file: 'emoji_34.png' }, '[弱]': { file: 'emoji_35.png' }, '[OK]': { file: 'emoji_36.png' }, '[拳头]': { file: 'emoji_37.png' }, '[胜利]': { file: 'emoji_38.png' }, '[鼓掌]': { file: 'emoji_39.png' }, '[握手]': { file: 'emoji_200.png' }, '[发怒]': { file: 'emoji_40.png' }, '[骷髅]': { file: 'emoji_41.png' }, '[便便]': { file: 'emoji_42.png' }, '[火]': { file: 'emoji_43.png' }, '[溜]': { file: 'emoji_44.png' }, '[爱心]': { file: 'emoji_45.png' }, '[心碎]': { file: 'emoji_46.png' }, '[钟情]': { file: 'emoji_47.png' }, '[唇]': { file: 'emoji_48.png' }, '[戒指]': { file: 'emoji_49.png' }, '[钻石]': { file: 'emoji_50.png' }, '[太阳]': { file: 'emoji_51.png' }, '[有时晴]': { file: 'emoji_52.png' }, '[多云]': { file: 'emoji_53.png' }, '[雷]': { file: 'emoji_54.png' }, '[雨]': { file: 'emoji_55.png' }, '[雪花]': { file: 'emoji_56.png' }, '[爱人]': { file: 'emoji_57.png' }, '[帽子]': { file: 'emoji_58.png' }, '[皇冠]': { file: 'emoji_59.png' }, '[篮球]': { file: 'emoji_60.png' }, '[足球]': { file: 'emoji_61.png' }, '[垒球]': { file: 'emoji_62.png' }, '[网球]': { file: 'emoji_63.png' }, '[台球]': { file: 'emoji_64.png' }, '[咖啡]': { file: 'emoji_65.png' }, '[啤酒]': { file: 'emoji_66.png' }, '[干杯]': { file: 'emoji_67.png' }, '[柠檬汁]': { file: 'emoji_68.png' }, '[餐具]': { file: 'emoji_69.png' }, '[汉堡]': { file: 'emoji_70.png' }, '[鸡腿]': { file: 'emoji_71.png' }, '[面条]': { file: 'emoji_72.png' }, '[冰淇淋]': { file: 'emoji_73.png' }, '[沙冰]': { file: 'emoji_74.png' }, '[生日蛋糕]': { file: 'emoji_75.png' }, '[蛋糕]': { file: 'emoji_76.png' }, '[糖果]': { file: 'emoji_77.png' }, '[葡萄]': { file: 'emoji_78.png' }, '[西瓜]': { file: 'emoji_79.png' }, '[光碟]': { file: 'emoji_80.png' }, '[手机]': { file: 'emoji_81.png' }, '[电话]': { file: 'emoji_82.png' }, '[电视]': { file: 'emoji_83.png' }, '[声音开启]': { file: 'emoji_84.png' }, '[声音关闭]': { file: 'emoji_85.png' }, '[铃铛]': { file: 'emoji_86.png' }, '[锁头]': { file: 'emoji_87.png' }, '[放大镜]': { file: 'emoji_88.png' }, '[灯泡]': { file: 'emoji_89.png' }, '[锤头]': { file: 'emoji_90.png' }, '[烟]': { file: 'emoji_91.png' }, '[炸弹]': { file: 'emoji_92.png' }, '[枪]': { file: 'emoji_93.png' }, '[刀]': { file: 'emoji_94.png' }, '[药]': { file: 'emoji_95.png' }, '[打针]': { file: 'emoji_96.png' }, '[钱袋]': { file: 'emoji_97.png' }, '[钞票]': { file: 'emoji_98.png' }, '[银行卡]': { file: 'emoji_99.png' }, '[手柄]': { file: 'emoji_100.png' }, '[麻将]': { file: 'emoji_101.png' }, '[调色板]': { file: 'emoji_102.png' }, '[电影]': { file: 'emoji_103.png' }, '[麦克风]': { file: 'emoji_104.png' }, '[耳机]': { file: 'emoji_105.png' }, '[音乐]': { file: 'emoji_106.png' }, '[吉他]': { file: 'emoji_107.png' }, '[火箭]': { file: 'emoji_108.png' }, '[飞机]': { file: 'emoji_109.png' }, '[火车]': { file: 'emoji_110.png' }, '[公交]': { file: 'emoji_111.png' }, '[轿车]': { file: 'emoji_112.png' }, '[出租车]': { file: 'emoji_113.png' }, '[警车]': { file: 'emoji_114.png' }, '[自行车]': { file: 'emoji_115.png' }
  }
};
for (let emoji in emojiList) {
  let emojiItem = emojiList[emoji];
  for (let key in emojiItem) {
    let item = emojiItem[key];
    item.img = `${emojiBaseUrl}/${emoji}/${item.file}`;
  }
}

let encode = function(_map, _content) {
  _content = '' + _content;
  if (!_map || !_content) {
    return _content || '';
  }
  return _content.replace(_map.r, function($1) {
    let _result = _map[!_map.i ? $1.toLowerCase() : $1];
    return _result != null ? _result : $1;
  });
};

let escape = (function() {
  let _reg = /<br\/?>$/;
  let _map = {
    r: /<|>|&|\r|\n|\s|'|"/g,
    '<': '&lt;',
    '>': '&gt;',
    '&': '&amp;',
    ' ': '&nbsp;',
    '"': '&quot;',
    '\'': '&#39;',
    '\n': '<br/>',
    '\r': ''
  };
  return function(_content) {
    _content = encode(_map, _content);
    return _content.replace(_reg, '<br/>');
  };
})();

其他

深入写代码的时候,发现和自己之前写小程序的时候差不多。把模型抽象好,之后的东西就很好弄了。要么是推送,要么是短链接请求。(短链接浏览器也有spdy/http2 的服用)

一般的模型是:

  1. 要有个会话列表:会话列表的增删改查
  2. 要有个聊天列表:聊天列表的增删改查
  3. 玩了,其他都是细节

这次使用了云信的API,发现他们包装得挺好的,和我之前自己包的模型差不多,IM的消息格式也和之前强哥设定的差不多。推荐使用他们进行接入咯。云信的细节参考他们自己的开源项目:

https://github.com/netease-im/NIM_Web_Demo

在这里插入图片描述

玩~

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值