web前端emoji表情

web前端emoji表情

随着互联网的发展,传统的文字已经不能满足人们生活交流的需要,有时一张图片,一个表情,更能传递想要表达的内容。(具体可参考微信斗图-_-! )如今比较有名的 emoji 已经可以被大部分设备所兼容,那么问题来了,如何在网页上显示一个emoji表情呢?

通常作为前端,我们接收到的表情不会是一张图片,而是类似 :smile : 、[微笑]、/微笑这样的字符串,那么如何将字符串转换为对应的表情就是问题的关键。毋庸置疑,通过正则表达式对相应的字符串作匹配替换,从而将对应的emoji表情显示出来是比较好的一个方法。

首先,本地要有一个emoji表情库,类似 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);
    }
}
 

转自https://blog.csdn.net/canlynet/article/details/84854330

发布了39 篇原创文章 · 获赞 63 · 访问量 26万+

猜你喜欢

转载自blog.csdn.net/qq_31967569/article/details/103984686
今日推荐