Last active
June 4, 2020 12:09
-
-
Save vthibault/b129cf2481aa9855407c37386e345d02 to your computer and use it in GitHub Desktop.
Detect emoji v2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://unicode.org/emoji/charts/full-emoji-list.html | |
// var list = Array.from(document.querySelectorAll('.chars')).map(t => t.textContent); | |
const ctx = document.createElement('canvas').getContext('2d'); | |
const CANVAS_HEIGHT = 25; | |
const CANVAS_WIDTH = 30; | |
/** | |
* @var {Object} cache | |
*/ | |
let cache = new Map(); | |
// Initialize convas context | |
ctx.font = '24px Arial, Sans-Serif'; | |
ctx.textBaseline = 'Top'; | |
ctx.canvas.width = CANVAS_WIDTH * 2; | |
ctx.canvas.height = CANVAS_HEIGHT; | |
/** | |
* Check if the two pixels parts are perfectly the sames | |
* | |
* @params {string} unicode | |
* @returns {boolean} | |
*/ | |
function isEmojiSupported(unicode) { | |
ctx.clearRect(0, 0, CANVAS_WIDTH * 2, CANVAS_HEIGHT); | |
// Draw in red on the left | |
ctx.fillStyle = '#FF0000'; | |
ctx.fillText(unicode, 0, 22); | |
// Draw in blue on right | |
ctx.fillStyle = '#0000FF'; | |
ctx.fillText(unicode, CANVAS_WIDTH, 22); | |
const a = ctx.getImageData(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT).data; | |
const count = a.length; | |
let i = 0; | |
// Search the first visible pixel | |
for (; i < count && !a[i + 3]; i += 4); | |
// No visible pixel | |
if (i >= count) { | |
return false; | |
} | |
// Emoji has immutable color, so we check the color of the emoji in two different colors | |
// the result show be the same. | |
const x = CANVAS_WIDTH + i / 4 % CANVAS_WIDTH; | |
const y = Math.floor(i / 4 / CANVAS_WIDTH); | |
const b = ctx.getImageData(x, y, 1, 1).data; | |
if (a[i] !== b[0] || a[i + 2] !== b[2]) { | |
return false; | |
} | |
// Some emojis are a contraction of different ones, so if it's not | |
// supported, it will show multiple characters | |
if (ctx.measureText(unicode).width >= CANVAS_WIDTH) { | |
return false; | |
} | |
return true; | |
} | |
/** | |
* Check if emoji is supported with cache | |
* | |
* @params {string} unicode | |
* @returns {boolean} | |
*/ | |
export function isSupported(unicode) { | |
if (cache.has(unicode)) { | |
return cache.get(unicode); | |
} | |
const supported = isEmojiSupported(unicode); | |
cache.set(unicode, supported); | |
return supported; | |
} | |
/** | |
* Request to handle cache directly | |
* | |
* @params {Map} store | |
*/ | |
export function setStore (store) { | |
cache = store; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment