Je ne sais pas si elle peut compter sur l'avenir (les navigateurs pourraient changer ce qui est montré pour les caractères non pris en charge), je ne suis pas sûr que cela est optimisé (comme je ne comprennent pas bien les limites idéales à mesurer ici), mais l'approche suivante (dessiner un texte sur toile et inspecter le résultat sous forme d'image) peut, si elle est examinée, fournir une vérification plus fiable et plus précise que largeur. Tout le code au début est juste une détection de navigateur que nous devons utiliser puisque la détection de fonction n'est pas possible.
(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);
MISE À JOUR 1
J'ai essayé de mettre à jour pour Firefox moderne (pour essayer de vérifier les chiffres hexadécimaux attendus dans la toile), et en vérifiant que, contrairement à mon code ci-dessus, la toile (et le motif pour le faire correspondre) était juste assez grand pour accueillir le plus grand caractère par context.measureText()
(U + 0BCC de mes tests, bien que probablement dépend de la police, dans mon cas "Arial Unicode MS"). Par https://bugzilla.mozilla.org/show_bug.cgi?id=442133#c9, cependant, measureText
répond actuellement par erreur au zoom pour seulement les caractères inconnus. Maintenant, si seulement un pouvait simuler le zoom dans le canevas JavaScript afin d'affecter ces mesures (et seulement ces mesures) ...
code disponible pour référence à https://gist.github.com/brettz9/1f061bb2ce06368db3e5
Pourquoi cette question wiki communautaire? –
Je ne me suis pas rendu compte qu'il y avait un inconvénient à marquer une question wiki communautaire. Mon erreur. –
L'ensemble des caractères qui seront affichés par un navigateur dépend plus des polices que l'utilisateur a installées que de son navigateur. Presque tous les navigateurs prennent en charge Unicode, et la plupart des personnages n'ont pas besoin de manipulation particulière. –