2017-10-09 4 views
1

EDIT: à l'origine, je n'ai vérifié que les navigateurs de bureau - mais avec les navigateurs mobiles, l'image est encore plus compliquée.Canvas.measureText différences sur les navigateurs sont énormes

Je suis tombé sur un problème étrange avec certains navigateurs et ses capacités de rendu de texte et je ne suis pas sûr de pouvoir faire quoi que ce soit pour éviter cela.

Il semble que WebKit et (moins cohérent) Firefox sur Android créent un texte légèrement plus grand en utilisant la bibliothèque Canvas 2D. Je voudrais ignorer l'apparence visuelle pour l'instant, mais plutôt se concentrer sur les mesures de texte, car ceux-ci peuvent être facilement comparés.

J'ai utilisé les deux méthodes communes pour calculer la largeur du texte:

  • Canvas 2D API et mesurer texte
  • méthode DOM

tel que décrit dans cette question: Calculate text width with JavaScript cependant, les deux donnent plus ou moins le même résultat (sur tous les navigateurs).

function getTextWidth(text, font) { 
    // if given, use cached canvas for better performance 
    // else, create new canvas 
    var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas")); 
    var context = canvas.getContext("2d"); 
    context.font = font; 
    var metrics = context.measureText(text); 
    return metrics.width; 
}; 

function getTextWidthDOM(text, font) { 
    var f = font || '12px arial', 
     o = $('<span>' + text + '</span>') 
      .css({'font': f, 'float': 'left', 'white-space': 'nowrap'}) 
      .css({'visibility': 'hidden'}) 
      .appendTo($('body')), 
     w = o.width(); 

    return w; 
} 

J'ai modifié le violon un peu en utilisant les polices Google qui permet d'effectuer des mesures de texte pour un ensemble de polices échantillons (s'il vous plaît attendre les WebFonts à charger avant de cliquer sur le bouton de mesure):

http://jsfiddle.net/aj7v5e4L/15/ (mis à jour à la force poids de police et le style)

l'exécution de ce sur différents navigateurs montre le problème que j'ai (en utilisant la chaîne « S »):

Measurements for the string 'S'

Les différences entre tous les navigateurs de bureau sont mineures - seul Safari se démarque comme ça - il est de l'ordre de 1% et 4% ce que j'ai vu, en fonction de la police. Donc ce n'est pas grand - mais jette mes calculs. MISE À JOUR: J'ai aussi testé quelques navigateurs mobiles - et sur iOS tous sont au même niveau que Safari (en utilisant WebKit sous le capot, donc pas de surprise) - et Firefox sur Android est très activé. J'ai lu que la précision du sous-pixel n'est pas vraiment supportée par tous les navigateurs (IE plus anciens par exemple) - mais arrondir même n'aide pas - car je peux alors avoir une largeur différente. L'utilisation de la police standard fournie avec le contexte renvoie exactement les mêmes mesures entre Chrome et Safari - donc je pense que c'est uniquement lié aux polices Web. Je suis un peu perplexe de ce que je pourrais faire maintenant - comme je pense que je fais juste quelque chose de mal car je n'ai rien trouvé sur le net - mais le violon est aussi simple que possible . J'ai passé toute la journée là-dessus vraiment - alors vous êtes mon seul espoir maintenant.

J'ai quelques solutions de contournement moche dans ma tête (par exemple rendre le texte sur les navigateurs affectés 4% plus petit) - que je voudrais vraiment éviter.

+0

Votre table de résultats a été faite avec la chaîne '" S "'? Si oui, j'ai '15.73333..' sur firefox pour android sur la première police, qui est plus proche de vos résultats de safari que de tout autre. Vous n'avez pas accès à un vrai clavier pour l'instant, mais que se passe-t-il lorsque vous forcez le poids de la police? – Kaiido

+0

Oui, a été créé avec la chaîne "S" - n'a même pas touché le royaume des navigateurs mobiles - qui pourrait ouvrir encore plus de problèmes;) - va essayer la police de poids – Michael

Répondre

1

Il semble que Safari (et quelques autres) ne supporte pas d'obtenir au niveau sous-pixel, mais ne dessine pas ...

Lorsque vous définissez votre taille de police à 9.5pt, cette valeur est convertie en 12.6666 ... px.

Même si Safari ne renvoie une valeur de haute précision pour cela:

console.log(getComputedStyle(document.body)['font-size']); 
 
// on Safari returns 12.666666984558105px oO
body{font-size:9.5pt}

il est incapable de tirer correctement à tailles de police non-entier, et non seulement sur une toile:

console.log(getRangeWidth("S", '12.3px serif')); 
 
// safari: 6.673828125 | FF 6.8333282470703125 
 
console.log(getRangeWidth("S", '12.4px serif')); 
 
// safari: 6.673828125 | FF 6.883331298828125 
 
console.log(getRangeWidth("S", '12.5px serif')); 
 
// safari 7.22998046875 | FF 6.95001220703125 
 
console.log(getRangeWidth("S", '12.6px serif')); 
 
// safari 7.22998046875 | FF 7 
 

 
// High precision DOM based measurement 
 
function getRangeWidth(text, font) { 
 
    var f = font || '12px arial', 
 
     o = $('<span>' + text + '</span>') 
 
      .css({'font': f, 'white-space': 'nowrap'}) 
 
      .appendTo($('body')), 
 
     r = document.createRange(); 
 
r.selectNode(o[0]); 
 
var w = r.getBoundingClientRect().width; 
 
o.remove(); 
 
return w; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Donc, afin d'éviter ces bizarreries, Essayez toujours d'utiliser px unité avec des valeurs entières.

+0

Ps: FF sur Android semble arrondir vraiment bizarrement : 12.3! = 12.4 == 12.5 == 12.6 ... – Kaiido

+0

Awesome - a eu un coup d'oeil rapide et avec des tailles de police entières en pixels, il semble en effet être cohérent (besoin de faire quelques vérifications supplémentaires). Un nouveau violon le démontre et permet de modifier la taille de la police à la volée: http://jsfiddle.net/aj7v5e4L/17/ Merci beaucoup Kaiido, ça m'a vraiment aidé. – Michael