前言
平时虽然使用过 emoji
,但是如果自己写,感觉上还是差点,这次就利用空闲实现自己试试 emoji
集成
github代码地址
插件
其实最开始集成 emoji
的时候,一点思路都没有,于是想着先去网上找下插件,就找到了 emoji插件 体验了一下还行,而且都是使用原生实现的,于是我就下载到本地,查看源码。
然后发现他那主要是是根据预先设置的数组的数据,来设置 class
类名改变雪碧背景图的定位
这个库的数据数组,是使用 emoji
字体作为 key
值的保留数据的
使用
1 2 3 4
| let str = "😠😩😲😞😵😰😒😍😤😜😝😋😘😚😷😳😃😅😆😁😂😊☺😄😢😭😨😣😡😌😖😔😱😪😏😓😥😫😉🐽👬👭🌲🌳🍋😎😀☀☁☔⛄⚡🌀🌁🌂🌃🌄🌅🌆🌇🌈❄⛅🌉🌊🌋🌌🌏🌑🌔🌓🌙🌕🌛🌟🌠🕐🕑🕒🕓🕔🕕🕖🕗🕘🕙🕚🕛⌚⌛⏰⏳♈♉♊♋♌♍♎♏♐♑♒♓⛎🍀🌷🌱🍁🌸🌹🍂🍃🌺🌻🌴🌵🌾🌽🍄🌰🌼🌿🍒🍌🍎🍊🍓🍉🍅🍆🍈🍍🍇🍑🍏👀👂👃👄👅💄💅💆💇💈👤👦👧👨👩👪👫👮👯👰👱👲👳👴👵👶👷👸👹👺👻👼👽👾👿💀💁💂💃🐌🐍🐎🐔🐗🐫🐘🐨🐒🐑🐙🐚🐛🐜🐝🐞🐠🐡🐢🐤🐥🐦🐣🐧🐩🐟🐬🐭🐯🐱🐳🐴🐵🐶🐷🐻🐹🐺🐮🐰🐸🐾🐲🐼😺😸😹😽😻😿😾😼🙀🙅🙆🙇🙈🙊🙉🙋🙌🙍🙎🙏🏠🏡🏢🏣🏥🏦🏧🏨🏩🏪🏫⛪⛲🏬🏯🏰🏭⚓🏮🗻🗼🗽🗾🗿👞👟👠👡👢👣👓👕👖👑👔👒👗👘👙👚👛👜👝💰💱💹💲💳💴💵💸🇨🇳🇩🇪🇪🇸🇫🇷🇬🇧🇮🇹🇯🇵🇰🇷🇷🇺🇺🇸🔥🔦🔧🔨🔩🔪🔫🔮🔯🔰🔱💉💊🅰🅱🆎🅾🎀🎁🎂🎄🎅🎌🎆🎈🎉🎍🎎🎓🎒🎏🎇🎐🎃🎊🎋🎑📟☎📞📱📲📝📠✉📨📩📪📫📮📰📢📣📡📤📥📦📧🔠🔡🔢🔣🔤✒💺💻✏📎💼💽💾💿📀✂📍📃📄📅📁📂📓📖📔📕📗📘📙📚📛📜📋📆📊📈📉📇📌📒📏📐📑🎽⚾⛳🎾⚽🎿🏀🏁🏂🏃🏄🏆🏈🏊🚃🚇Ⓜ🚄🚅🚗🚙🚌🚏🚢✈⛵🚉🚀🚤🚕🚚🚒🚑🚓⛽🅿🚥🚧🚨♨⛺🎠🎡🎢🎣🎤🎥🎦🎧🎨🎩🎪🎫🎬🎭🎮🀄🎯🎰🎱🎲🎳🎴🃏🎵🎶🎷🎸🎹🎺🎻🎼〽📷📹📺📻📼💋💌💍💎💏💐💑💒🔞©®™ℹ#⃣1⃣2⃣3⃣4⃣5⃣6⃣7⃣8⃣9⃣0⃣🔟📶📳📴🍔🍙🍰🍜🍞🍳🍦🍟🍡🍘🍚🍝🍛🍢🍣🍱🍲🍧🍖🍥🍠🍕🍗🍨🍩🍪🍫🍬🍭🍮🍯🍤🍴☕🍸🍺🍵🍶🍷🍻🍹↗↘↖↙⤴⤵↔↕⬆⬇➡⬅▶◀⏩⏪⏫⏬🔺🔻🔼🔽⭕❌❎❗⁉‼❓❔❕〰➰➿❤💓💔💕💖💗💘💙💚💛💜💝💞💟♥♠♦♣🚬🚭♿🚩⚠⛔♻🚲🚶🚹🚺🛀🚻🚽🚾🚼🚪🚫✔🆑🆒🆓🆔🆕🆖🆗🆘🆙🆚🈁🈂🈲🈳🈴🈵🈶🈚🈷🈸🈹🈯🈺㊙㊗🉐🉑➕➖✖➗💠💡💢💣💤💥💦💧💨💩💪💫💬✨✴✳⚪⚫🔴🔵🔲🔳⭐⬜⬛▫▪◽◾◻◼🔶🔷🔸🔹❇💮💯↩↪🔃🔊🔋🔌🔍🔎🔒🔓🔏🔐🔑🔔☑🔘🔖🔗🔙🔚🔛🔜🔝✅✊✋✌👊👍☝👆👇👈👉👋👏👌👎👐" document.querySelector(".emojiOne").innerHTML = jEmoji.unifiedToHTML(str)
|
修改
- 在使用的过程中,提示的文字是英文,但是我们的用户一般是国人,所以我就将标签的提示文字改成了中文
- 这个库动态生成是靠
unifiedToHTML
这个函数。我想着如果之后集成的时候。是需要保存到数据,然后就将 emoji
字体作为自定义属性放在了 span
上,并且由于 span
是追加在可编辑的 div
内。所以也继承了可编辑的特性,有点问题,这个之后稍后会提到
- 因为这个库只会返回一堆处理之后的
span
标签字符串,并没有弄进输入框的方法,然后我就想着自己试下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| let editEle = document.querySelector(".data-input");
let spans = document.querySelectorAll(".emoji");
var lastEditRange;
editEle.onkeyup = function () { var selection = getSelection(); lastEditRange = selection.getRangeAt(0); }; editEle.onkeydown=function(e){ console.log(e) }
editEle.onclick = function (e) { let focusDomClassList = Array.prototype.slice.call(e.target.classList); this.focus(); var selection = window.getSelection(); lastEditRange = selection.getRangeAt(0); for (let index = 0; index < spans.length; index++) { const element = spans[index]; element.onclick = function (e) { let targetDOM = e.target.outerHTML; _insertimg(targetDOM) } } }
function _insertimg(str) { var selection = window.getSelection ? window.getSelection() : document.selection; document.querySelector(".data-input").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) }
|
坑
- 光标的对象以及属性兼容不是很好,而且很难找到比较完善的文档
- 修改之后,如果光标点在编辑框内的某个表情前面。光标就会定在
span
双标签内,这也就是我给 contenteditable="true"
属性的原因
- 当表情跟文字一起的时候,光标定在表情后面的时候,删除不了表情。但是这个时候如果点击的光标后没有其他元素文字的时候,还是可以删除的。这个问题,我尝试了一下,是双标签的问题,换成
img
上面的问题都没有
后记
无意中在网上翻文章的时候,发现了 twemoji
这个库。这个库是 Twitter
和 Iconfactory
联合制作的 twemoji
完全开源
插件地址
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| // 将插件放在页面中 <script src="https://twemoji.maxcdn.com/v/latest/twemoji.min.js" crossorigin="anonymous"></script>
<script>
let dataStr ="😠😩😲😞😵😰😒😍😤😜😝😋😘😚😷😳😃😅😆😁😂😊☺😄😢😭😨😣😡😌😖😔😱😪😏😓😥😫😉🐽👬👭🌲🌳🍋😎😀☀☁☔⛄⚡🌀🌁🌂🌃🌄🌅🌆🌇🌈❄⛅🌉🌊🌋🌌🌏🌑🌔🌓🌙🌕🌛🌟🌠🕐🕑🕒🕓🕔🕕🕖🕗🕘🕙🕚🕛⌚⌛⏰⏳♈♉♊♋♌♍♎♏♐♑♒♓⛎🍀🌷🌱🍁🌸🌹🍂🍃🌺🌻🌴🌵🌾🌽🍄🌰🌼🌿🍒🍌🍎🍊🍓🍉🍅🍆🍈🍍🍇🍑🍏👀👂👃👄👅💄💅💆💇💈👤👦👧👨👩👪👫👮👯👰👱👲👳👴👵👶👷👸👹👺👻👼👽👾👿💀💁💂💃🐌🐍🐎🐔🐗🐫🐘🐨🐒🐑🐙🐚🐛🐜🐝🐞🐠🐡🐢🐤🐥🐦🐣🐧🐩🐟🐬🐭🐯🐱🐳🐴🐵🐶🐷🐻🐹🐺🐮🐰🐸🐾🐲🐼😺😸😹😽😻😿😾😼🙀🙅🙆🙇🙈🙊🙉🙋🙌🙍🙎🙏🏠🏡🏢🏣🏥🏦🏧🏨🏩🏪🏫⛪⛲🏬🏯🏰🏭⚓🏮🗻🗼🗽🗾🗿👞👟👠👡👢👣👓👕👖👑👔👒👗👘👙👚👛👜👝💰💱💹💲💳💴💵💸🇨🇳🇩🇪🇪🇸🇫🇷🇬🇧🇮🇹🇯🇵🇰🇷🇷🇺🇺🇸🔥🔦🔧🔨🔩🔪🔫🔮🔯🔰🔱💉💊🅰🅱🆎🅾🎀🎁🎂🎄🎅🎌🎆🎈🎉🎍🎎🎓🎒🎏🎇🎐🎃🎊🎋🎑📟☎📞📱📲📝📠✉📨📩📪📫📮📰📢📣📡📤📥📦📧🔠🔡🔢🔣🔤✒💺💻✏📎💼💽💾💿📀✂📍📃📄📅📁📂📓📖📔📕📗📘📙📚📛📜📋📆📊📈📉📇📌📒📏📐📑🎽⚾⛳🎾⚽🎿🏀🏁🏂🏃🏄🏆🏈🏊🚃🚇Ⓜ🚄🚅🚗🚙🚌🚏🚢✈⛵🚉🚀🚤🚕🚚🚒🚑🚓⛽🅿🚥🚧🚨♨⛺🎠🎡🎢🎣🎤🎥🎦🎧🎨🎩🎪🎫🎬🎭🎮🀄🎯🎰🎱🎲🎳🎴🃏🎵🎶🎷🎸🎹🎺🎻🎼〽📷📹📺📻📼💋💌💍💎💏💐💑💒🔞©®™ℹ#⃣1⃣2⃣3⃣4⃣5⃣6⃣7⃣8⃣9⃣0⃣🔟📶📳📴🍔🍙🍰🍜🍞🍳🍦🍟🍡🍘🍚🍝🍛🍢🍣🍱🍲🍧🍖🍥🍠🍕🍗🍨🍩🍪🍫🍬🍭🍮🍯🍤🍴☕🍸🍺🍵🍶🍷🍻🍹↗↘↖↙⤴⤵↔↕⬆⬇➡⬅▶◀⏩⏪⏫⏬🔺🔻🔼🔽⭕❌❎❗⁉‼❓❔❕〰➰➿❤💓💔💕💖💗💘💙💚💛💜💝💞💟♥♠♦♣🚬🚭♿🚩⚠⛔♻🚲🚶🚹🚺🛀🚻🚽🚾🚼🚪🚫✔🆑🆒🆓🆔🆕🆖🆗🆘🆙🆚🈁🈂🈲🈳🈴🈵🈶🈚🈷🈸🈹🈯🈺㊙㊗🉐🉑➕➖✖➗💠💡💢💣💤💥💦💧💨💩💪💫💬✨✴✳⚪⚫🔴🔵🔲🔳⭐⬜⬛▫▪◽◾◻◼🔶🔷🔸🔹❇💮💯↩↪🔃🔊🔋🔌🔍🔎🔒🔓🔏🔐🔑🔔☑🔘🔖🔗🔙🔚🔛🔜🔝✅✊✋✌👊👍☝👆👇👈👉👋👏👌👎👐";
let div = document.createElement('div'); div.textContent =dataStr; document.body.appendChild(div); twemoji.parse(document.querySelector("div"))
div.textContent =dataStr; document.body.appendChild(div); twemoji.parse(document.querySelector("div"),{ folder: 'svg', ext: '.svg' })
</script>
|
意外获得
Node.textContent
作用其实跟 innerText
作用差不多,但是 innerText
设置会引起网页重绘,并且innerText
性能比不上 textContent
,使用 textContent
插入的属于文本形式,可以有效的防止 XSS
攻击。
评论加载中