我想知道我是否可以检测我的实际字体是否支持字符串的所有字符。例如,我们可以看到不支持的字符用Times New Roman填充,而正常文本用选定的字体填充:
但我想首先把整个文本与相同的字体,如果一个字符是不支持的,太切换字体与Arial。你知道我该怎么做吗?
dced5bon1#
ctx.font使用与CSS's font shorthand相同的语法(忽略行高参数),因此您可以使用与CSS相同的方式指定备用字体,即在末尾添加多个字体系列值:
ctx.font
font
ctx.font = "10px 'your font', Arial";
3pvhb19x2#
要同时进行回退,您可以使用measureText,通过检查每个字母与回退字体的度量来检测是否有字母正在使用回退字体。请注意,理想情况下,您应该检查每个字素,而不是每个代码点。JavaScript的for-of循环迭代字符串的代码点,但有grapheme-splitter这样的库可以帮助迭代字素。这个解决方案的性能可能不是很好,但是对于短文本来说应该是不错的,特别是如果你缓存结果的话。注意如果你缓存它,你应该确保你的字体在缓存之前被加载,以避免在字体加载时缓存失效,最好是在测试之前,因为在这种情况下它必须回退。
measureText
for
of
/* const splitter = new GraphemeSplitter(); */ const font = "JinxedWizards"; const fallbackFont = "Arial, sans-serif"; const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); function usesFallback(text) { for (const grapheme of /*splitter.iterateGraphemes*/(text)) { ctx.font = "20px " + font + ", " + fallbackFont; const metrics = ctx.measureText(grapheme); ctx.font = "20px " + fallbackFont; const fallbackMetrics = ctx.measureText(grapheme); if ( metrics.width === fallbackMetrics.width && metrics.actualBoundingBoxAscent === fallbackMetrics.actualBoundingBoxAscent && metrics.actualBoundingBoxDescent === fallbackMetrics.actualBoundingBoxDescent && metrics.actualBoundingBoxLeft === fallbackMetrics.actualBoundingBoxLeft && metrics.actualBoundingBoxRight === fallbackMetrics.actualBoundingBoxRight /* fontBoundingBoxAscent seems to give different results somehow... don't ask me why! metrics.fontBoundingBoxAscent === fallbackMetrics.fontBoundingBoxAscent && metrics.fontBoundingBoxDescent === fallbackMetrics.fontBoundingBoxDescent */ ) { //console.log("fallback detected for", grapheme, metrics, fallbackMetrics); return true; } else { //console.log("differs for", grapheme, metrics, fallbackMetrics); } } return false; } console.log("usesFallback('testing')", usesFallback('testing')); console.log("usesFallback('testing œ')", usesFallback('testing œ')); // manually verify that we can display the font document.body.append(canvas); ctx.font = "20px " + font + ", " + fallbackFont; ctx.fillText("testing œ", 50, 50);
2条答案
按热度按时间dced5bon1#
ctx.font
使用与CSS'sfont
shorthand相同的语法(忽略行高参数),因此您可以使用与CSS相同的方式指定备用字体,即在末尾添加多个字体系列值:3pvhb19x2#
要同时进行回退,您可以使用
measureText
,通过检查每个字母与回退字体的度量来检测是否有字母正在使用回退字体。请注意,理想情况下,您应该检查每个字素,而不是每个代码点。JavaScript的
for
-of
循环迭代字符串的代码点,但有grapheme-splitter这样的库可以帮助迭代字素。这个解决方案的性能可能不是很好,但是对于短文本来说应该是不错的,特别是如果你缓存结果的话。注意如果你缓存它,你应该确保你的字体在缓存之前被加载,以避免在字体加载时缓存失效,最好是在测试之前,因为在这种情况下它必须回退。