依赖于emoji 库,主要是雪碧图实现表情的统一。
采用div标签的contenteditable属性实现编辑功能。 难点在于选择表情时的光标位置保存。实现任意光标位置插入表情。
实现一个小小的demo供大家参考, 共同学习!
部分代码仅供参考,共同学习
难点部分;
1、选择表情时的光标位置保存
// 保存上次光标位置信息
var lastEditRange;
var editEle = document.getElementById('edit');
// 编辑框点击事件
editEle.onclick = function() {
// 获取选定对象
var selection = getSelection();
// 设置最后光标对象
lastEditRange = selection.getRangeAt(0);
};
// 编辑框按键弹起事件
editEle.onkeyup = function() {
// 获取选定对象
var selection = getSelection();
// 设置最后光标对象
lastEditRange = selection.getRangeAt(0);
};
2、在任意位置插入表情
function _insertimg(str) {
var selection = window.getSelection
? window.getSelection()
: document.selection;
document.getElementById(elName).focus();
if (lastEditRange) {
// 存在最后光标对象,选定对象清除所有光标并添加最后光标还原之前的状态
selection.removeAllRanges();
selection.addRange(lastEditRange);
}
var range = selection.createRange
? selection.createRange()
: selection.getRangeAt(0);
if (!window.getSelection) {
var selection = window.getSelection
? window.getSelection()
: document.selection;
var range = selection.createRange
? selection.createRange()
: selection.getRangeAt(0);
range.pasteHTML(str);
range.collapse(false);
range.select();
} else {
var hasR = range.createContextualFragment(str);
var hasR_lastChild = hasR.lastChild;
while (
hasR_lastChild &&
hasR_lastChild.nodeName.toLowerCase() == 'br' &&
hasR_lastChild.previousSibling &&
hasR_lastChild.previousSibling.nodeName.toLowerCase() == 'br'
) {
var e = hasR_lastChild;
hasR_lastChild = hasR_lastChild.previousSibling;
hasR.removeChild(e);
}
range.insertNode(hasR);
if (hasR_lastChild) {
range.setEndAfter(hasR_lastChild);
range.setStartAfter(hasR_lastChild);
}
range.collapse(false);
selection.removeAllRanges();
selection.addRange(range);
}
// 无论如何都要记录最后光标对象
lastEditRange = selection.getRangeAt(0);
}
3、表情字符转义
function emojiToUnicode(emoji) {
var backStr = '';
if (emoji && emoji.length > 0) {
for (var char of emoji) {
var index = char.codePointAt(0);
if (index > 65535) {
var h =
'\\u' +
(Math.floor((index - 0x10000) / 0x400) + 0xd800).toString(
16
);
var c =
'\\u' + ((index - 0x10000) % 0x400 + 0xdc00).toString(16);
backStr = backStr + h + c;
} else {
backStr = backStr + char;
}
}
console.log(backStr);
}
return backStr;
}
function utf16toEntities(str) {
//检测utf16emoji表情 转换为实体字符以供后台存储
var patt = /[\ud800-\udbff][\udc00-\udfff]/g;
str = str.replace(patt, function(char) {
var H, L, code;
if (char.length === 2) {
//辅助平面字符(我们需要做处理的一类)
H = char.charCodeAt(0); // 取出高位
L = char.charCodeAt(1); // 取出低位
code = (H - 0xd800) * 0x400 + 0x10000 + L - 0xdc00; // 转换算法
return '&#' + code + ';';
} else {
return char;
}
});
return str;
}
console.log('ssss---->', emojiToUnicode('��adfa我们'));
// console.log('utf16toEntities222222--->', utf16toEntities('\ud83d\ude00adfa我们'))
$('.box').append(utf16toEntities('\ud83d\ude00adfa我们'));