Wenn ich einen Text in eine Leinwand mit einer Schriftart zeichne, die über @ font-face geladen wird, wird der Text nicht richtig angezeigt. Es wird überhaupt nicht angezeigt (in Chrome 13 und Firefox 5) oder die Schrift ist falsch (Opera 11). Diese Art von unerwartetem Verhalten tritt nur bei der ersten Zeichnung mit der Schrift auf. Danach funktioniert alles gut.
Ist es das Standardverhalten oder so?
Danke dir.
PS: Es folgt der Quellcode des Testfalls
<!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>
Antworten:
Das Zeichnen auf Leinwand muss erfolgen und sofort zurückkehren, wenn Sie die
fillText
Methode aufrufen . Der Browser hat die Schriftart jedoch noch nicht aus dem Netzwerk geladen, was eine Hintergrundaufgabe ist. Es muss also auf die verfügbare Schriftart zurückgreifen .Wenn Sie sicherstellen möchten, dass die Schriftart verfügbar ist, laden Sie ein anderes Element auf der Seite vor, z. B.:
quelle
display: none
, aber dies könnte dazu führen, dass Browser das Laden der Schriftart überspringen. Es ist besser, ein Leerzeichen anstelle eines zu verwenden.
.Verwenden Sie diesen Trick und binden Sie ein
onerror
Ereignis an einImage
Element.Demo hier : funktioniert auf dem neuesten Chrome.
quelle
src
Attribut festgelegt ist, beginnt das Laden im nächsten Ausführungsblock.Der Kern des Problems besteht darin, dass Sie versuchen, die Schriftart zu verwenden, der Browser sie jedoch noch nicht geladen und möglicherweise nicht einmal angefordert hat. Was Sie brauchen, ist etwas, das die Schriftart lädt und Ihnen einen Rückruf gibt, sobald sie geladen ist; Sobald Sie den Rückruf erhalten, wissen Sie, dass es in Ordnung ist, die Schriftart zu verwenden.
Schauen Sie sich den WebFont Loader von Google an . Es scheint, als würde ein "benutzerdefinierter" Anbieter und ein
active
Rückruf nach dem Laden funktionieren.Ich habe es noch nie benutzt, aber nach einem kurzen Scan der Dokumente müssen Sie eine CSS-Datei erstellen
fonts/pressstart2p.css
, wie folgt :Fügen Sie dann das folgende JS hinzu:
quelle
Sie können Schriftarten mit der FontFace-API laden, bevor Sie sie im Canvas verwenden:
Die Schriftartressource
myfont.woff2
wird zuerst heruntergeladen. Sobald der Download abgeschlossen ist, wird die Schriftart dem FontFaceSet des Dokuments hinzugefügt .Die Spezifikation der FontFace-API ist zum Zeitpunkt dieses Schreibens ein Arbeitsentwurf. Siehe Browserkompatibilitätstabelle hier.
quelle
document.fonts.add
. Siehe Brunos Antwort.Was ist mit der Verwendung von einfachem CSS, um ein Div mit der folgenden Schriftart auszublenden:
CSS:
HTML:
quelle
https://drafts.csswg.org/css-font-loading/
quelle
Ich bin kürzlich auf das Problem gestoßen, als ich damit gespielt habe. http://people.opera.com/patrickl/experiments/canvas/scroller/
Sie haben dies umgangen, indem Sie die Schriftfamilie direkt im CSS zur Zeichenfläche hinzugefügt haben, sodass Sie sie einfach hinzufügen können
canvas {Schriftfamilie: PressStart; }}
quelle
Ich bin nicht sicher, ob dies Ihnen helfen wird, aber um das Problem mit meinem Code zu lösen, habe ich einfach eine for-Schleife oben in meinem Javascript erstellt, die alle Schriftarten durchlief, die ich laden wollte. Ich habe dann eine Funktion ausgeführt, um die Leinwand zu löschen und die gewünschten Elemente auf der Leinwand vorzuladen. Bisher hat es perfekt funktioniert. Das war meine Logik. Ich habe meinen Code unten gepostet:
quelle
Ich habe eine jsfiddle geschrieben, die die meisten der hier vorgeschlagenen Korrekturen enthält, aber keine hat das Problem behoben. Ich bin jedoch ein unerfahrener Programmierer und habe die vorgeschlagenen Korrekturen möglicherweise nicht richtig codiert:
http://jsfiddle.net/HatHead/GcxQ9/23/
HTML:
CSS:
JS:
Problemumgehung Ich gab schließlich nach und verwendete beim ersten Laden ein Bild des Textes, während ich den Text mit den Schriftflächen außerhalb des Leinwandanzeigebereichs positionierte. Alle nachfolgenden Anzeigen der Schriftarten im Canvas-Anzeigebereich funktionierten problemlos. Dies ist keineswegs eine elegante Problemumgehung.
Die Lösung ist in meine Website integriert, aber wenn jemand sie benötigt, werde ich versuchen, eine jsfiddle zu erstellen, um dies zu demonstrieren.
quelle
Einige Browser unterstützen die CSS- Spezifikation zum Laden von Schriftarten . Sie können sich registrieren und einen Rückruf registrieren, wenn alle Schriftarten geladen wurden. Sie können das Zeichnen Ihrer Leinwand (oder zumindest das Zeichnen von Text in Ihre Leinwand) bis dahin verzögern und eine Neuzeichnung auslösen, sobald die Schriftart verfügbar ist.
quelle
Verwenden Sie zunächst den Web Font Loader von Google, wie in der anderen Antwort empfohlen, und fügen Sie Ihren Zeichnungscode zu dem darin enthaltenen Rückruf hinzu, um anzuzeigen, dass die Schriftarten geladen wurden. Dies ist jedoch nicht das Ende der Geschichte. Ab diesem Punkt ist es sehr browserabhängig. Meistens funktioniert es einwandfrei, aber manchmal kann es erforderlich sein, einige hundert Millisekunden zu warten oder die Schriftarten an einer anderen Stelle auf der Seite zu verwenden. Ich habe verschiedene Optionen ausprobiert und die einzige Methode, die afaik immer funktioniert, besteht darin, schnell einige Testnachrichten mit der Kombination aus Schriftfamilie und Schriftgröße, die Sie verwenden möchten, in die Zeichenfläche zu zeichnen. Sie können dies mit der gleichen Farbe wie der Hintergrund tun, sodass sie nicht einmal sichtbar sind und es sehr schnell geht. Danach funktionierten Schriftarten immer für mich und in allen Browsern.
quelle
Meine Antwort bezieht sich eher auf Google Web-Schriftarten als auf @ font-face. Ich habe überall nach einer Lösung für das Problem gesucht, dass die Schrift nicht auf der Leinwand angezeigt wird. Ich habe Timer, setInterval, Font-Delay-Bibliotheken und alle möglichen Tricks ausprobiert. Nichts hat geklappt. (Einschließlich Einfügen der Schriftfamilie in das CSS für Zeichenfläche oder der ID des Zeichenflächenelements.)
Ich fand jedoch, dass das Animieren von Text, der in einer Google-Schriftart gerendert wurde, problemlos funktioniert. Was ist der Unterschied? In der Leinwandanimation zeichnen wir die animierten Elemente immer wieder neu. So kam mir die Idee, den Text zweimal zu rendern.
Das hat auch nicht funktioniert - bis ich auch eine kurze (100ms) Timer-Verzögerung hinzugefügt habe. Ich habe bisher nur auf einem Mac getestet. Chrome funktionierte bei 100 ms einwandfrei. Safari erforderte ein erneutes Laden der Seite, daher erhöhte ich den Timer auf 1000, und dann war es in Ordnung. Firefox 18.0.2 und 20.0 würden nichts auf die Leinwand laden, wenn ich Google-Schriftarten (einschließlich der Animationsversion) verwenden würde.
Vollständiger Code: http://www.macloo.com/examples/canvas/canvas10.html
http://www.macloo.com/examples/canvas/scripts/canvas10.js
quelle
Steht vor dem gleichen Problem. Nachdem ich "bobince" und andere Kommentare gelesen habe, verwende ich folgendes Javascript, um es zu umgehen:
quelle
Wenn Sie jedes Mal neu zeichnen möchten, wenn eine neue Schriftart geladen wird (und wahrscheinlich das Rendering ändern), hat die API zum Laden von Schriftarten auch dafür ein schönes Ereignis . Ich hatte Probleme mit dem Versprechen in einer vollständig dynamischen Umgebung.
quelle
Die Leinwand wird unabhängig vom Laden des DOM gezeichnet. Die Vorladetechnik funktioniert nur, wenn die Leinwand nach dem Vorladen gezeichnet wird.
Meine Lösung, auch wenn es nicht die beste ist:
CSS:
HTML:
JavaScript:
quelle
Ich versuche, FontFaceSet.load zu verwenden, um das Problem zu beheben: https://jsfiddle.net/wengshenshun/gr1zkvtq/30
Die Browserkompatibilität finden Sie unter https://developer.mozilla.org/en-US/docs/Web/API/FontFaceSet/load
quelle
In diesem Artikel wurden meine Probleme behoben, bei denen faul geladene Schriftarten nicht angezeigt wurden.
Laden von Web-Schriftarten, um Leistungsprobleme zu vermeiden und das Laden von Seiten zu beschleunigen
Das hat mir geholfen ...
quelle
Fügen Sie eine Verzögerung wie unten hinzu
quelle