Nicht sicher, ob es auf geht nach vorn verlassen kann (Browser könnte sich ändern, was für nicht unterstützte Zeichen angezeigt wird), noch bin ich, dass sicher, dass diese optimiert ist (wie ich Ich habe kein gutes Verständnis für die idealen Grenzen, die hier zu messen sind), aber der folgende Ansatz (Zeichnen von Text in Canvas und Betrachten des Ergebnisses als Bild) kann, falls überprüft, eine zuverlässigere und genauere Überprüfung liefern, als dies möglich wäre Breite. Der gesamte Code am Anfang ist nur eine Browser-Erkennung, die wir verwenden müssen, da eine Merkmalserkennung nicht möglich ist.
(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);
UPDATE 1
ich für moderne Firefox zu aktualisieren versucht (um zu versuchen, für die erwarteten hexadezimalen Ziffern innerhalb der Leinwand zu überprüfen), und überprüft, um sicherzustellen, im Gegensatz zu meinem Code über die Leinwand (und passendes Muster) war gerade groß genug, um das breiteste Zeichen pro context.measureText()
aufzunehmen (U + 0BCC von meinen Tests, obwohl vermutlich abhängig von Schriftart, in meinem Fall "Arial Unicode MS"). Per https://bugzilla.mozilla.org/show_bug.cgi?id=442133#c9 reagiert jedoch measureText
derzeit irrtümlich auf den Zoom nur für die unbekannten Zeichen. Nun, wenn nur einer den Zoom in JavaScript-Canvas simulieren könnte, um diese Messungen (und nur diese Messungen) zu beeinflussen ...
-Code verfügbar Referenz bei https://gist.github.com/brettz9/1f061bb2ce06368db3e5
Warum ist diese Frage Community Wiki? –
Ich wusste nicht, dass es einen Nachteil beim Markieren eines Frage-Community-Wikis gab. Mein Fehler. –
Die Anzahl der Zeichen, die von einem Browser angezeigt werden, hängt mehr von den Zeichensätzen ab, die der Benutzer installiert hat, als von dem jeweiligen Browser. So gut wie alle Browser unterstützen Unicode, und die meisten Zeichen benötigen keine besondere Behandlung. –