Le dessin du texte <canvas> avec @font-face ne fonctionne pas la première fois
Lorsque je dessine un texte dans une toile avec une police de caractères qui est chargé via @font-face, le texte n'est pas affiché correctement. Il ne montre pas du tout (dans Chrome 13 et Firefox 5), ou la police de caractère est mal (Opera 11). Ce type de comportement inattendu se produit uniquement lors de la première du dessin avec la police de caractères. Après, tout fonctionne bien.
C'est le comportement standard ou quelque chose?
Merci.
PS: voici le code source du cas de test
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>@font-face and <canvas></title>
<style id="css">
@font-face {
font-family: 'Press Start 2P';
src: url('fonts/PressStart2P.ttf');
}
</style>
<style>
canvas, pre {
border: 1px solid black;
padding: 0 1em;
}
</style>
</head>
<body>
<h1>@font-face and <canvas></h1>
<p>
Description: click the button several times, and you will see the problem.
The first line won't show at all, or with a wrong typeface even if it does.
<strong>If you have visited this page before, you may have to refresh (or reload) it.</strong>
</p>
<p>
<button id="draw">#draw</button>
</p>
<p>
<canvas width="250" height="250">
Your browser does not support the CANVAS element.
Try the latest Firefox, Google Chrome, Safari or Opera.
</canvas>
</p>
<h2>@font-face</h2>
<pre id="view-css"></pre>
<h2>Script</h2>
<pre id="view-script"></pre>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script id="script">
var x = 30,
y = 10;
$('#draw').click(function () {
var canvas = $('canvas')[0],
ctx = canvas.getContext('2d');
ctx.font = '12px "Press Start 2P"';
ctx.fillStyle = '#000';
ctx.fillText('Hello, world!', x, y += 20);
ctx.fillRect(x - 20, y - 10, 10, 10);
});
</script>
<script>
$('#view-css').text($('#css').text());
$('#view-script').text($('#script').text());
</script>
</body>
</html>
- Les navigateurs chargement de la police dans le fond, de manière asynchrone. Ce comportement est normal. Voir aussi paulirish.com/2009/fighting-the-font-face-fout
Vous devez vous connecter pour publier un commentaire.
Dessin sur la toile qui doit arriver et de revenir immédiatement lorsque vous appelez la
fillText
méthode. Toutefois, le navigateur n'a pas encore chargés de la police à partir du réseau, ce qui est une tâche de fond. Donc, il doit revenir à la police, elle ne disponibles.Si vous voulez assurez-vous que la police est disponible, avoir un autre élément sur la page de la précharge, par exemple.:
display: none
, mais qui pourrait causer des navigateurs pour passer en chargeant la police. Il est préférable d'utiliser un espace au lieu d'un.
.font-family
. Si, par exemple, une police spécifique de poids est souhaitée, alors que la police de poids doit être chargé, par exemple en utilisant des polices de poids sur la maquette div.Utilisation cette astuce et le lier à une
onerror
événement à unImage
élément.Démo ici: fonctionne sur le dernier Chrome.
src
attribut est défini, le chargement va se lancer dans la prochaine exécution du bloc.Là le cœur du problème est que vous essayez d'utiliser la police, mais le navigateur n'a pas chargé de encore et, éventuellement, n'a même pas demandé. Ce que vous avez besoin est quelque chose qui se charge de la police et de vous donner un rappel une fois qu'il est chargé; une fois que vous obtenez le rappel, vous savez qu'il est acceptable d'utiliser la police de caractères.
Regarder Google WebFont Chargeur; il semble comme un "custom" prestataire et un
active
de rappel après la charge de la faire fonctionner.Je n'ai jamais utilisé avant, mais à partir d'une analyse rapide de la documentation vous avez besoin de faire un fichier css
fonts/pressstart2p.css
, comme ceci:Puis ajouter l'JS:
Qu'en utilisant de simples CSS pour masquer un div à l'aide de la police comme ceci:
CSS:
HTML:
Vous pouvez charger des polices avec le FontFace API avant de l'utiliser dans la toile:
La ressource de police
myfont.woff2
est d'abord téléchargé. Une fois le téléchargement terminé, la police est ajoutée au document de FontFaceSet.La spécification de la FontFace API est un projet de travail à la rédaction de ce document. Voir tableau de compatibilité du navigateur ici.
document.fonts.add
. Voir la réponse de bruno.https://drafts.csswg.org/css-font-loading/
je suis tombé sur le problème lors de la lecture avec elle récemment http://people.opera.com/patrickl/experiments/canvas/scroller/
travaillé autour d'elle en ajoutant à font-family toile directement dans le CSS, donc vous pouvez simplement ajouter
toile { font-family: PressStart; }
Je ne suis pas sûr si cela va vous aider, mais pour résoudre le problème avec mon code, je l'ai tout simplement créé une boucle en haut de mon code Javascript qui a couru à travers toutes les polices que j'ai voulu charger. J'ai ensuite couru une fonction pour effacer de la toile et de la précharge les éléments que je voulais sur la toile. Jusqu'à présent, il a travaillé à la perfection. C'était ma logique, j'ai posté mon code ci-dessous:
J'ai écrit un jsfiddle intégrant la plupart des corrections suggérées ici, mais aucun n'a résolu le problème. Cependant, je suis un programmeur novice alors peut-être n'a pas de code les corrections suggérées correctement:
http://jsfiddle.net/HatHead/GcxQ9/23/
HTML:
CSS:
JS:
Solution de contournement
J'ai finalement cédé et, sur la première charge, utilisé une image du texte en plus de positionner le texte avec la police-est confrontée à l'extérieur de la toile zone d'affichage. Tous les écrans de la police-les visages dans la toile de la zone d'affichage travaillé pas de problème. Ce n'est pas une élégante solution de contournement par tous les moyens.
La solution est cuit dans mon site mais si quelqu'un a besoin je vais essayer de créer un jsfiddle à démontrer.
Certains les navigateurs prennent en charge la CSS Chargement de Polices spécification. Il vous permet d'enregistrer enregistrer un rappel pour quand toutes les polices ont été chargés. Vous pouvez retarder le dessin de votre toile (ou au moins le dessin du texte dans la zone de travail) jusqu'alors, et de déclencher une redessiner une fois que la police est disponible.
Tout d'abord l'utilisation de Google Web fonts chargeur comme cela a été conseillé dans l'autre réponse et ajouter votre code de dessin à la fonction de rappel qu'il fournit à indiquer les polices ont été chargés. Cependant, ce n'est pas la fin de l'histoire. À partir de ce moment, il est très navigateur dépendante. La plupart du temps, cela fonctionnera très bien, mais parfois il peut être nécessaire d'attendre quelques centaines de millisecondes ou utiliser les polices quelque part sur la page. J'ai essayé les différentes options et l'une méthode qui, autant que je sache fonctionne toujours est de dessiner rapidement des messages de test dans la zone de travail avec la famille de police et taille de police combinaisons que vous allez utiliser. Vous pouvez le faire avec la même couleur que l'arrière-plan, de sorte qu'ils ne seront pas visible et cela va arriver très vite. Après que les polices toujours travaillé pour moi et dans tous les navigateurs.
Ma réponse adresses polices Web de Google plutôt que @font-face. J'ai cherché partout pour trouver une solution au problème de la police ne s'affiche pas dans le canevas. J'ai essayé de minuteries, de setInterval, la police de retard des bibliothèques, et toutes sortes de trucs. Rien n'a fonctionné. (Y compris la mise à la police-famille dans le CSS pour la toile ou l'ID de l'élément canvas.)
Cependant, j'ai trouvé que animation texte rendu dans un de polices Google a travaillé facilement. Quelle est la différence? Dans la toile de l'animation, nous re-dessiner les objets animés, encore et encore. J'ai donc eu l'idée de rendre le texte deux fois.
Qui ne fonctionne pas, soit -- jusqu'à ce que j'ai également ajouté un court (100 ms) minuterie de retard. Je ne l'ai testé sur un Mac jusqu'à présent. Chrome a bien fonctionné à 100 millisecondes. Safari requis un rechargement de la page, donc j'ai augmenté la minuterie à 1 000, et alors, il était beau. Firefox 18.0.2 et 20,0 ne serait pas de charger quoi que ce soit sur la toile si j'ai été en utilisant Google polices (y compris l'animation de la version).
Code complet: http://www.macloo.com/examples/canvas/canvas10.html
http://www.macloo.com/examples/canvas/scripts/canvas10.js
Faces d'un même problème. Après la lecture de "bobince" et autres commentaires, j'utilise javascript suivant pour le contourner :
Si vous voulez redessiner à chaque fois une nouvelle police est chargé (et probablement changer le rendu) la police de chargement de l'api a une belle l'événement pour que, trop. J'ai eu des problèmes avec la Promesse dans un environnement dynamique.
La toile est tiré de la DOM de chargement. La précharge technique ne fonctionne que si la toile est établi après la précontrainte.
Ma solution, même si elle n'est pas la meilleure:
CSS:
HTML:
JavaScript:
J'essaie d'utiliser FontFaceSet.la charge de résoudre le problème:
https://jsfiddle.net/wengshenshun/gr1zkvtq/30
Vous pouvez trouver la compatibilité du navigateur de https://developer.mozilla.org/en-US/docs/Web/API/FontFaceSet/load
Ajouter un délai que ci-dessous