web前端emoji表情
随着互联网的发展,传统的文字已经不能满足人们生活交流的需要,有时一张图片,一个表情,更能传递想要表达的内容。(具体可参考微信斗图-_-! )如今比较有名的 emoji 已经可以被大部分设备所兼容,那么问题来了,如何在网页上显示一个emoji表情呢?
通常作为前端,我们接收到的表情不会是一张图片,而是类似 :smile : 、[微笑]、/微笑这样的字符串,那么如何将字符串转换为对应的表情就是问题的关键。毋庸置疑,通过正则表达式对相应的字符串作匹配替换,从而将对应的emoji表情显示出来是比较好的一个方法。
首先,本地要有一个emoji表情库,类似 或者一个雪碧图
本地表情文件的不同,对应的处理方法也会不一样。 有了这样的一个表情库文件,接下来就是对相应的表情字符串进行匹配。
其次:匹配,就免不了要用到正则表达式,针对不同的表情字符串,需要写不同的匹配规则。如需匹配[微笑]或者/微笑格式的表情,对应的正则如下
//对于元字符 如 [] {} + ? 等,需要转义
var reg = new RegExp("\\[" + emoji.name + "\\]|\\/" + emoji.name, "gm");
写好了匹配规则,接下来要对需要转换的字符串进行替换。 replace()很好的帮我们解决了这个问题。
var result = input.replace(reg, '<img class="emoji" src="' + emoji.src + '"/>');
那么问题来了,在这两行code中,用到了emoji.name,emoji.src,这个emoji对象到底是个什么样的东西。其实这个emoji对象相当于一个emoji配置,他的code长这个样子:
var emojis = [{
name: '微笑',
src: 'emoji/default/0.png'
}, {
name: '撇嘴',
src: 'emoji/default/1.png'
}, {
name: '发呆',
src: 'emoji/default/3.png'
}]
我们用到的emoji则是其中的一个个对象。最后,我们需要循环这个数组,将每个对应的字符串匹配成对应的表情。完整代码如下:
function filterEmoji(input, emoji) {
var regexp = new RegExp('\\[' + emoji.name + '\\]|\\/' + emoji.name, 'gm');
var result = input.replace(regexp, '<img class="emoji" src="' + emoji.src + '"/>');
return result;
}
function emoji($sce) {
return function(input) {
// 循环emojis配置表,匹配对应表情
emojis.forEach(function(emoji) {
input = filterEmoji(input, emoji);
});
//这里由于angular的安全限制,使用$sce将匹配到的表情转换为可识别的标签。
return $sce.trustAsHtml(input);
};
}
最后,在需要转换表情的地方,加上这个emoji过滤器就Ok了。
当然,这种方法有一个弊端就是需要加载很多的emoji表情图片,可以优化为用一张雪碧图去搞定。 在写法上也要有一些变化。首先肯定不能再通过标签去显示每一张表情图片,而是通过css添加background来实现。我们需要一个css的配置文件去匹配每个表情对应的雪碧图的位置。
.emoji {
display: inline-block;
background: url(emoji/default/emoji.png) no-repeat;
width: 21px;
height: 21px
}
.emoji.emoji_dai {
background-position: 0 0
}
.emoji.emoji_smile {
background-position: -21px 0
}
emojis也需要做一些修改
var emojis = [{
name: '微笑',
css: 'emoji_smile'
}, {
name: '发呆',
css: 'emoji_dai'
}]
匹配函数修改为:
function filterEmoji(input, emoji) {
var regexp = new RegExp('\\[' + emoji.name + '\\]|\\/' + emoji.name, 'gm');
var result = input.replace(regexp,"<i class='emoji" + b + "></i>");
}
最后,一个完整的emoji表情匹配到底结束。
转自https://mmmaming.github.io/mmmaming.github.io/web%E5%89%8D%E7%AB%AFemoji%E8%A1%A8%E6%83%85/
QQ聊天对话框(Js实现,支持表情插入文本中间)
一般我们做文本对话框,都考虑使用textarea,其实,用div也可以实现,用div的好处就是可以往里插入图片、表情等,不必都显示为字符。
但是在插入表情图片或插入图片时就面临一个问题,图片怎么才能放到我输入文本的中间位置,而不是每次都追加到最后面,百度搜索了很多资料,自己试过,包装好了两种方法,一种是针对div的,一种针对textarea,当然,textarea没法显示图片,只适用于插入表情后将代表表情的字符串插入到文本中间。
代码如下:
// 在光标位置插入内容(仅适用于textarea文本输入框)
function insertValueAtCursor(myField, insertContent) {
if (myField != document.activeElement) {
myField.value = myField.value + insertContent;
return;
}
//IE support
if (document.selection) {
myField.focus();
var sel = document.selection.createRange();
sel.text = insertContent;
sel.select();
}
//MOZILLA/NETSCAPE support
else if (typeof myField.selectionStart === 'number' || typeof myField.selectionEnd == 'number') {
var startPos = myField.selectionStart;
var endPos = myField.selectionEnd;
console.log("startPos:" + startPos)
// save scrollTop before insert
var restoreTop = myField.scrollTop;
myField.value = myField.value.substring(0, startPos) + insertContent + myField.value.substring(endPos, myField.value.length);
if (restoreTop > 0) {
// restore previous scrollTop
myField.scrollTop = restoreTop;
}
myField.focus();
myField.selectionStart = startPos + insertContent.length;
myField.selectionEnd = startPos + insertContent.length;
} else {
console.log('OK')
myField.value += insertContent;
myField.focus();
}
}
// 在光标位置插入html代码,如果dom没有获取到焦点则追加到最后
function insertAtCursor(dom, html) {
if (dom != document.activeElement) { // 如果dom没有获取到焦点,追加
dom.innerHTML = dom.innerHTML + html;
return;
}
var sel, range;
if (window.getSelection) {
// IE9 或 非IE浏览器
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
// Range.createContextualFragment() would be useful here but is
// non-standard and not supported in all browsers (IE9, for one)
var el = document.createElement("div");
el.innerHTML = html;
var frag = document.createDocumentFragment(),
node, lastNode;
while ((node = el.firstChild)) {
lastNode = frag.appendChild(node);
}
range.insertNode(frag);
// Preserve the selection
if (lastNode) {
range = range.cloneRange();
range.setStartAfter(lastNode);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
}
} else if (document.selection && document.selection.type != "Control") {
// IE < 9
document.selection.createRange().pasteHTML(html);
}
}