思路
- 渲染好
emoji列表
,为每个emoji图标
绑定点击事件。 emoji
是通过unicode16
进行展示的,需要将其插入textarea
或者input
的innerhtml
中才能展示出来。再将其赋值给value
,这样value
就包含了所有的输入内容。- 在点击插入
emoji
时,需要先获取textarea
或input
的innerhtml
和光标位置
。如果光标位置
和innerhtml长度
是相等的,说明是从后面插入,直接拼接字符串即可。如果不相等说明是从中间插入,需要先分割html
再拼接字符串。 - 注意重新设置光标位置,每一个
emoji
占用2个字符
,光标位置是加2
的。设置光标位置的方法是element.setSelectionRange(start,end)
。这也是从MDN找到的。
鸣谢
效果
源码
gitee仓库地址 emoji资源也在里面。
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>使用emoji</title>
<style>
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
.app {
width: 100%;
height: 100vh;
background-color: #f5f5f5;
}
.main {
width: 1080px;
min-width: 1080px;
height: 100%;
margin: 0 auto;
padding: 16px 24px;
box-sizing: border-box;
background-color: #fff;
}
.toolbar {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
box-sizing: border-box;
}
.emoji-btn {
cursor: pointer;
font-size: 18px;
color: #909090;
}
.primary-btn {
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
background-color: #409eff;
border: 1px solid #409eff;
color: #fff;
-webkit-appearance: none;
text-align: center;
box-sizing: border-box;
outline: none;
margin: 0;
transition: 0.1s;
font-weight: 500;
padding: 12px 20px;
font-size: 14px;
border-radius: 4px;
}
.primary-btn:active,
.primary-btn:hover {
background: #66b1ff;
border-color: #66b1ff;
color: #fff;
}
.textarea {
width: 100%;
height: 80px;
margin-top: 16px;
}
.clearfix {
width: 100%;
display: flex;
flex-wrap: wrap;
}
li {
list-style: none;
margin: 6px;
}
.content {
margin-top: 24px;
width: 100%;
color: #323233;
font-size: 16px;
font-weight: bold;
}
</style>
<script src="/lib/jquery-3.6.0.min.js"></script>
<script src="/lib/emoji-lib/emoji-list-with-image.js"></script>
<script src="/lib/emoji-lib/punycode.js"></script>
<script src="/lib/emoji-lib/punycode.min.js"></script>
<script src="/lib/emoji-lib/emoji.js"></script>
</head>
<body>
<div class="app">
<div class="main">
<p>发布动态</p>
<textarea
class="textarea"
maxlength="280"
value=""
oninput="handleInput(this)"
></textarea>
<div class="toolbar">
<span class="emoji-btn">表情</span>
<button class="primary-btn">发布动态</button>
</div>
<div class="emoji">
<div class="emoji-cont"></div>
</div>
<div class="content"></div>
</div>
</div>
<script type="text/javascript" src="./index.js"></script>
</body>
</html>
index.js
$(function () {
function initEmoji () {
$(".emoji-cont").html("");
renderEmoji();
// 点击表情
$(".emoji-icon").each(function (k, v) {
$(v).click(function () {
var textarea_cursorPosition = $(".textarea").getCursorPosition()
var textarea_innerhtmlLength = $(".textarea").html().length
var code = $(this).attr("unicode16");
// 光标在最后的情况
if (textarea_innerhtmlLength === textarea_cursorPosition) {
// emoji表情的字符串放进innerHtml才展示的了,直接放在value是字符形式
$(".textarea").html($(".textarea").html() + (parse("&#" + parseInt(code, 16) + ";")))
// 把innerHtml的内容放进textarea的value
$(".textarea").val($(".textarea").html())
} else { // 光标在中间
var originHtml = $(".textarea").html()
var newHtml = originHtml.slice(0, textarea_cursorPosition) + parse("&#" + parseInt(code, 16) + ";") + originHtml.slice(textarea_cursorPosition)
$(".textarea").html(newHtml)
$(".textarea").val($(".textarea").html())
}
$(".textarea").focus()
// 一个emoji占2个字符所以+2
$(".textarea")[0].setSelectionRange(textarea_cursorPosition + 2, textarea_cursorPosition + 2)
});
});
$(".emoji-cont").hide();
}
initEmoji();
// 点击展示表情
function showEmoji () {
$(".emoji-cont").toggle();
}
// 表情列表
function renderEmoji () {
var emos = getEmojiList()[0];
var html = '<ul class="clearfix">';
for (var j = 0; j < emos.length; j++) {
var emo = emos[j];
var data = "data:image/png;base64," + emo[2];
if (j % 20 == 0) {
html += '<li class="">';
} else {
html += "<li>";
}
html +=
'<img style="display: inline;vertical-align: middle;" src="' +
data +
'" unicode16="' +
emo[1] +
'" class="emoji-icon" /></li>';
}
$(".emoji-cont").append(html);
}
// 表情 通过该方法 可以直接把表情在输入框中显示出来。
function parse (arg) {
if (typeof ioNull != "undefined") {
return ioNull.emoji.parse(arg);
}
return "";
}
// 点击展示表情列表
$(".emoji-btn").click(() => {
showEmoji();
});
// 获取光标位置方法
(function ($, undefined) {
$.fn.getCursorPosition = function () {
var el = $(this).get(0);
var pos = 0;
if ('selectionStart' in el) {
pos = el.selectionStart;
} else if ('selection' in document) {
el.focus();
var Sel = document.selection.createRange();
var SelLength = document.selection.createRange().text.length;
Sel.moveStart('character', -el.value.length);
pos = Sel.text.length - SelLength;
}
return pos;
}
})(jQuery);
// 发布动态
$(".primary-btn").click(() => {
$(".emoji-cont").hide();
$(".content").html($(".textarea").val())
})
});
// 处理输入框输入
function handleInput (e) {
$(".textarea").val(e.value)
$(".textarea").html(e.value)
}