是否可以檢測客戶端是否支持特定的Unicode字符,或者它是否會呈現爲缺失的字形框?使用JavaScript檢測單個Unicode字符支持
重要提示:在儘可能多的瀏覽器支持儘可能
不重要:效率,速度,或優雅
我能想到的是用帆布嘗試的唯一方法,所以我想我會問在我開始走下那條路之前。
謝謝!
編輯:這不適用於公共網站;我只是想編譯每個瀏覽器支持的字符列表。
是否可以檢測客戶端是否支持特定的Unicode字符,或者它是否會呈現爲缺失的字形框?使用JavaScript檢測單個Unicode字符支持
重要提示:在儘可能多的瀏覽器支持儘可能
不重要:效率,速度,或優雅
我能想到的是用帆布嘗試的唯一方法,所以我想我會問在我開始走下那條路之前。
謝謝!
編輯:這不適用於公共網站;我只是想編譯每個瀏覽器支持的字符列表。
如果您想最大化瀏覽器支持,您可能不希望依賴任何JavaScript。許多移動瀏覽器甚至不支持它。
如果瀏覽器不支持字符集,什麼是回退?用另一種語言顯示內容?也許鏈接一個網站,按需轉換語言將更加強大。
我想編譯每個瀏覽器支持的字符列表,而不是最大限度地支持公共頁面。 – 2009-12-17 00:23:54
這是不是一個真正的答案更野生的想法:
如果你能找到你知道總是呈現爲缺失字形箱一個字符,你可以使用同樣的技術,因爲這javascript font detector --render字符和缺失的字形框外並比較它們的寬度。如果它們不同,那麼你就知道這個角色並不是呈現爲缺失的字形框。當然,這對固定寬度的字體根本不起作用,並且對於其中許多字符具有相同寬度的其他字體,它可能有很多固定的否定。
您可以始終使用charCodeAt()方法評估每個字符。這將返回unicode字符值。根據你在做什麼,你可以將你想接受的範圍限制爲「有效」的字符......如果你複製了「盒子」中的字符,你可以使用Web上的字符翻譯器來查看相應的unicode值是。
這裏有一個,我用Google搜索,發現:enter link description here
不能確定它是否能在前進的依據(瀏覽器可能會改變什麼是顯示了不支持的字符),我也沒有肯定,這是優化(如我對這裏測量的理想邊界沒有很好的理解),但是如果審查的話,以下方法(在畫布上繪製文本並將結果作爲圖像進行檢查)可以提供比檢查更爲可靠和準確的檢查寬度。所有的代碼在開始時只是瀏覽器檢測,我們必須使用,因爲功能檢測是不可能的。
(function() {
// http://www.quirksmode.org/js/detect.html
var BrowserDetect = {
init: function() {
this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
this.version = this.searchVersion(navigator.userAgent)
|| this.searchVersion(navigator.appVersion)
|| "an unknown version";
this.OS = this.searchString(this.dataOS) || "an unknown OS";
},
searchString: function (data) {
for (var i=0;i<data.length;i++) {
var dataString = data[i].string;
var dataProp = data[i].prop;
this.versionSearchString = data[i].versionSearch || data[i].identity;
if (dataString) {
if (dataString.indexOf(data[i].subString) != -1)
return data[i].identity;
}
else if (dataProp)
return data[i].identity;
}
},
searchVersion: function (dataString) {
var index = dataString.indexOf(this.versionSearchString);
if (index == -1) return;
return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
},
dataBrowser: [
{
string: navigator.userAgent,
subString: "Chrome",
identity: "Chrome"
},
{ string: navigator.userAgent,
subString: "OmniWeb",
versionSearch: "OmniWeb/",
identity: "OmniWeb"
},
{
string: navigator.vendor,
subString: "Apple",
identity: "Safari",
versionSearch: "Version"
},
{
prop: window.opera,
identity: "Opera",
versionSearch: "Version"
},
{
string: navigator.vendor,
subString: "iCab",
identity: "iCab"
},
{
string: navigator.vendor,
subString: "KDE",
identity: "Konqueror"
},
{
string: navigator.userAgent,
subString: "Firefox",
identity: "Firefox"
},
{
string: navigator.vendor,
subString: "Camino",
identity: "Camino"
},
{ // for newer Netscapes (6+)
string: navigator.userAgent,
subString: "Netscape",
identity: "Netscape"
},
{
string: navigator.userAgent,
subString: "MSIE",
identity: "Explorer",
versionSearch: "MSIE"
},
{
string: navigator.userAgent,
subString: "Gecko",
identity: "Mozilla",
versionSearch: "rv"
},
{ // for older Netscapes (4-)
string: navigator.userAgent,
subString: "Mozilla",
identity: "Netscape",
versionSearch: "Mozilla"
}
],
dataOS : [
{
string: navigator.platform,
subString: "Win",
identity: "Windows"
},
{
string: navigator.platform,
subString: "Mac",
identity: "Mac"
},
{
string: navigator.userAgent,
subString: "iPhone",
identity: "iPhone/iPod"
},
{
string: navigator.platform,
subString: "Linux",
identity: "Linux"
}
]
};
BrowserDetect.init();
/**
* Checks whether a given character is supported in the specified font. If the
* font argument is not provided, it will default to sans-serif, the default
* of the canvas element
* @param {String} chr Character to check for support
* @param {String} [font] Font Defaults to sans-serif
* @returns {Boolean} Whether or not the character is visually distinct from characters that are not supported
*/
function characterInFont (chr, font) {
var data,
size = 10, // We use 10 to confine results (could do further?) and minimum required for 10px
x = 0,
y = size,
canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
// Necessary?
canvas.width = size;
canvas.height = size;
if (font) { // Default of canvas is 10px sans-serif
font = size + 'px ' + font; // Fix size so we can test consistently
/**
// Is there use to confining by this height?
var d = document.createElement("span");
d.font = font;
d.textContent = chr;
document.body.appendChild(d);
var emHeight = d.offsetHeight;
document.body.removeChild(d);
alert(emHeight); // 19 after page load on Firefox and Chrome regardless of canvas height
//*/
}
ctx.fillText(chr, x, y);
data = ctx.getImageData(0, 0, ctx.measureText(chr).width, canvas.height).data; // canvas.width
data = Array.prototype.slice.apply(data);
function compareDataToBox (data, box, filter) {
if (filter) { // We can stop making this conditional if we confirm the exact arrays will continue to work, or otherwise remove and rely on safer full arrays
data = data.filter(function (item) {
return item != 0;
});
}
return data.toString() !== box;
}
var missingCharBox;
switch (BrowserDetect.browser) {
case 'Firefox': // Draws nothing
missingCharBox = '';
break;
case 'Opera':
//missingCharBox = '0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,197,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,73,0,0,0,0,0,0,0,0,0,0,0,36,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,36,0,0,0,0,0,0,0,0,0,0,0,36,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,36,0,0,0,0,0,0,0,0,0,0,0,36,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,36,0,0,0,0,0,0,0,0,0,0,0,36,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,36,0,0,0,0,0,0,0,0,0,0,0,197,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,73,0,0,0,0';
missingCharBox = '197,255,255,255,255,73,36,36,36,36,36,36,36,36,197,255,255,255,255,73';
break;
case 'Chrome':
missingCharBox = '2,151,255,255,255,255,67,2,26,2,26,2,26,2,26,2,26,2,26,2,26,2,26,2,151,255,255,255,255,67';
break;
case 'Safari':
missingCharBox = '17,23,23,23,23,5,52,21,21,21,21,41,39,39,39,39,39,39,39,39,63,40,40,40,40,43';
break;
default:
throw 'characterInFont() not tested successfully for this browser';
}
return compareDataToBox(data, missingCharBox, true);
}
// EXPORTS
((typeof exports !== 'undefined') ? exports : this).characterInFont = characterInFont;
}());
var r1 = characterInFont('a', 'Arial'); // true
var r2 = characterInFont('\uFAAA', 'Arial'); // false
alert(r1);
alert(r2);
更新1
我嘗試更新的現代火狐(嘗試檢查畫布內的預期十六進制數字),並檢查,以確保,不像我上面的代碼,畫布(和模式來匹配它)只是足夠大,以適應每context.measureText()
(U + 0BCC從我的測試,儘管可能依賴於字體,在我的情況下「Arial Unicode MS」)的最寬字符。每https://bugzilla.mozilla.org/show_bug.cgi?id=442133#c9,但是,measureText
目前錯誤地響應縮放只有未知的字符。現在,如果只有一個人可以模擬JavaScript canvas中的縮放以影響這些度量(並且僅影響這些度量)......
Brett的解決方案現在不再適用於Firefox,因爲它現在在找不到字符時在一個框中顯示十六進制Unicode代碼點。 – 2014-06-20 21:09:15
@AnonymousCoward:此刻更新了Firefox的另一個障礙...... – 2014-06-22 10:53:51
爲什麼這個問題社區wiki? – 2009-12-15 23:25:11
我沒有意識到標記問題社區wiki有一個缺點。我的錯。 – 2009-12-17 00:22:55
由瀏覽器顯示的一組字符更多取決於用戶安裝的字體而非瀏覽器。幾乎所有的瀏覽器都支持Unicode,大多數字符不需要任何特殊處理。 – 2010-01-06 01:33:21