![](/img/trans.png)
[英]How can I detect an emoji insert event from the OS X character viewer and iOS emoji keyboard in Javascript/Redactor?
[英]How can I detect rendering support for emoji in JavaScript?
我想将表情符号添加到我的网站,但如果平台不支持它们,则隐藏它们,而不是显示小方块。
我觉得这是不可能的,但有人不同意吗? 如何才能做到这一点?
绘制一个字形(在供应商最流行的表情符号范围内,在 Unicode 联盟的表情符号范围内,如快乐脸、亲吻、悲伤脸等)以canvas
并使用getImageData
读取像素。 如果您感兴趣的像素的 Alpha 通道data[3]
不透明(例如在 ??? 的中心),否则,它可能是一个表情符号😗
function supportsEmoji () { const ctx = document.createElement("canvas").getContext("2d"); ctx.canvas.width = ctx.canvas.height = 1; ctx.fillText("😗", -4, 4); return ctx.getImageData(0, 0, 1, 1).data[3] > 0; // Not a transparent pixel } console.log( supportsEmoji() );
或类似的东西...
在 Chrome、Firefox、IE11、Edge、Safari 中测试了上述内容
Safari 返回false
,IE11 虽然有 Emoji 但没有颜色返回true
。
旗帜表情符号是这里发布的答案的一个边缘案例。 由于如果设备不支持标志表情符号,则会呈现国家/地区代码的后备。 例如,英国国旗 (🇬🇧) 将变为 -> GB。
Windows 10 不支持表情符号标志。
此脚本使用与现有答案类似的方法,但会检查画布是否为灰度。 如果画布中有颜色,我们就知道渲染了一个表情符号。
function supportsFlagEmoji () {
var canvas = document.createElement("canvas");
canvas.height = 10;
canvas.width = canvas.height*2;
var ctx = canvas.getContext("2d");
ctx.font = canvas.height+"px Arial";
ctx.fillText("🇬🇧", 0, canvas.height);
var data = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
var i = 0;
while(i<data.length) {
if (data[i] !== data[i+1] || data[i] !== data[i+2]) return true;
i+=4;
}
return false;
}
接受的答案不适用于我的系统(Windows 10/chrome)。 对于不受支持的字形,它返回 true,对于不覆盖中心像素但实际上已渲染 (☹) 的表情符号,它似乎不准确。
我的系统绘制的不受支持的字形,似乎可以互换,是: 和
. 当然第一个的中心像素是不透明的,也许这就是原因。
另一种方法是将不受支持的字形绘制到画布中(您可以使用 \ 这是一个有保证的非字符,请参阅https://en.wikipedia.org/wiki/Specials_(Unicode_block) ),然后“校验和”或者只是对getImageData()
的结果求和,然后根据这些数字检查您的表情符号。 这样您就不会依赖于字形的实现,只要系统显示“未找到”符号。 Firefox 似乎显示不受支持的表情符号的唯一十六进制代码,因此此方法不适用于该浏览器或类似配置。
第二种方法,更准确但在我的使用中要慢得多,是使用toDataURL()
进行比较:
我在运行所有三种方法的片段测试中也包含了“双重不受支持”的表情符号。 作为记录,我现在在 CodePen 的演示中使用“rgb sum”方法来确保输出中不会出现空白表情符号,并且不会错误地过滤掉任何内容。
var c = document.createElement("canvas") var ctx = c.getContext("2d"); const em = 16; c.width = em; c.height = em; ["\", "\\", "🖤", "☺", "☹", "💀", "☠", "🩴"].forEach(e => console.log(e + ":using center pixel:" + supports(e) + ",using checksum:" + supports2(e) + ",using toDataURL:" + supports3(e))); //using center pixel detection function supports(e) { let ctx = document.createElement("canvas").getContext("2d"); ctx.fillText(e, -2, 4); return ctx.getImageData(0, 0, 1, 1).data[3] > 0; // Not a transparent pixel } //using checksum method function supports2(e) { //https://en.wikipedia.org/wiki/Specials_(Unicode_block) (NON-Character) var unsupported = ["\", "\\"].map(b => { ctx.clearRect(0, 0, em, em); ctx.fillText(b, 0, em); let d = ctx.getImageData(0, 0, em, em).data let sum = d.reduce((acc, cur) => { return acc + cur }) return sum }); ctx.clearRect(0, 0, em, em); ctx.fillText(e, 0, em); let d = ctx.getImageData(0, 0, em, em).data let sum = d.reduce((acc, cur) => { return acc + cur }) return !unsupported.some(b => b == sum) } //using toDataURL() method function supports3(e) { ctx.clearRect(0, 0, em, em); ctx.fillText(e, 0, em); let emo = c.toDataURL() ctx.clearRect(0, 0, em, em); ctx.fillText('\', 0, em); let bad1 = c.toDataURL() ctx.clearRect(0, 0, em, em); ctx.fillText('\\', 0, em); let bad2 = c.toDataURL() return (emo != bad1) && (emo != bad2) }
如果有人正在寻找图书馆,那么这里是一个if-emoji
。 它使用 Roko 在他的回答中使用的相同方法。
这是一种依赖于表情符号几乎总是方形纵横比(或接近方形纵横比)这一事实的方法。 不支持表情符号的浏览器通常会将它们呈现为一个细长的矩形“”,或者对于字素簇表情符号,将其呈现为一系列字符“♂”。
/** Check if browser probably supports native emoji rendering
* @param {string} emoji - which emoji to use to test; a multicharacter emoji (grapheme
* cluster) will have lower chance of false positives; common emojis (smiley face),
* sometimes have unicode alternatives the browser will render
* @returns {boolean}
*/
function supports_emoji(emoji="🤦🏼♂️"){
const el = document.createElement("div");
el.style = "position:absolute;visibility:hidden;";
el.textContent = emoji;
document.body.appendChild(el);
const size = el.getBoundingClientRect();
el.remove();
// expecting a roughly square emoji; incorrectly rendered grapheme clusters will be
// rendered as multiple characters (width > height), while single character emojis are
// usually rendered as a thinner rectangle (height > width)
const square = Math.abs(1-size.width/size.height);
return square < .23;
}
作为旁注,您可以考虑使用Noto Emoji 字体,而不用担心检查表情符号支持。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.