使用JavaScript检测单个Unicode字符支持

i-g*_*i-g 24 javascript unicode cross-browser

是否可以检测客户端是否支持特定的Unicode字符,或者是否将其呈现为缺少的字形框?

重要提示:支持尽可能多的浏览器

不重要:效率,速度或优雅

我能想到的唯一方法是使用画布,所以我想在开始走这条路之前我会问.

谢谢!

编辑:这不适用于公共网站; 我只是想编译每个浏览器支持的字符列表.

Ann*_*nie 9

这是一个疯狂的想法,而不是一个真正的答案:

如果你能找到一个你知道的字符总是呈现为一个丢失的字形框,你可以使用与这个javascript字体检测器相同的技术 - 在屏幕外渲染字符和缺少的字形框并比较它们的宽度.如果它们不同,那么您知道该字符不会呈现为缺少的字形框.当然,这对于固定宽度字体根本不起作用,并且对于许多字符宽度相同的其他字体,它可能有很多固定底片.

  • 这不适用于每个角色,但如果你提高字体大小,你应该得到很好的结果.我仍然喜欢这个答案...某种奇怪的但它可以工作:-) (3认同)

Don*_*uck 7

您可以使用画布来检查该字符的渲染是否与您知道不支持的字符相同。U+FFFF是比较字符的一个不错的选择,因为它保证不是一个有效的 unicode 字符

因此,您创建一个画布来渲染U+FFFF角色,并创建另一个画布来渲染要测试的角色。然后,您可以使用该方法通过比较两个画布的数据 URL 来进行比较toDataURL。如果画布相同,则测试字符的渲染方式与不受支持的U+FFFF字符相同,这意味着它不受支持;如果画布不相同,则测试字符的渲染方式与不受支持的字符不同,因此受支持。

以下代码执行此操作:

//The first argument is the character you want to test, and the second argument is the font you want to test it in.
//If the second argument is left out, it defaults to the font of the <body> element.
//The third argument isn't used under normal circumstances, it's just used internally to avoid infinite recursion.
function characterIsSupported(character, font = getComputedStyle(document.body).fontFamily, recursion = false){
    //Create the canvases
    let testCanvas = document.createElement("canvas");
    let referenceCanvas = document.createElement("canvas");
    testCanvas.width = referenceCanvas.width = testCanvas.height = referenceCanvas.height = 150;

    //Render the characters
    let testContext = testCanvas.getContext("2d");
    let referenceContext = referenceCanvas.getContext("2d");
    testContext.font = referenceContext.font = "100px " + font;
    testContext.fillStyle = referenceContext.fillStyle = "black";
    testContext.fillText(character, 0, 100);
    referenceContext.fillText('\uffff', 0, 100);
    
    //Firefox renders unsupported characters by placing their character code inside the rectangle making each unsupported character look different.
    //As a workaround, in Firefox, we hide the inside of the character by placing a black rectangle on top of it.
    //The rectangle we use to hide the inside has an offset of 10px so it can still see part of the character, reducing the risk of false positives.
    //We check for Firefox and browers that behave similarly by checking if U+FFFE is supported, since U+FFFE is, just like U+FFFF, guaranteed not to be supported.
    if(!recursion && characterIsSupported('\ufffe', font, true)){
        testContext.fillStyle = referenceContext.fillStyle = "black";
        testContext.fillRect(10, 10, 80, 80);
        referenceContext.fillRect(10, 10, 80, 80);
    }

    //Check if the canvases are identical
    return testCanvas.toDataURL() != referenceCanvas.toDataURL();
}

//Examples
console.log("a is supported: " + characterIsSupported('a'));    //Returns true, 'a' should be supported in all browsers
console.log("\ufffe is supported: " + characterIsSupported('\ufffe'));    //Returns false, U+FFFE is guaranteed to be unsupported just like U+FFFF
console.log("\u2b61 is supported: " + characterIsSupported('\u2b61'));    //Results vary depending on the browser. At the time of writing this, this returns true in Chrome on Windows and false in Safari on iOS.
console.log("\uf8ff is supported: " + characterIsSupported('\uf8ff'));    //The unicode Apple logo is only supported on Apple devices, so this should return true on Apple devices and false on non-Apple devices.
Run Code Online (Sandbox Code Playgroud)


Cha*_*ert -4

如果您想最大化浏览器支持,您可能不想依赖 javascript 来完成任何事情。许多移动浏览器甚至不支持它。

如果浏览器不支持字符集,有什么办法呢?以另一种语言显示内容?也许链接一个按需切换语言的网站会更强大。