Cuando dibujo un texto en un lienzo con un tipo de letra que se carga a través de @ font-face, el texto no se muestra correctamente. No se muestra en absoluto (en Chrome 13 y Firefox 5), o el tipo de letra es incorrecto (Opera 11). Este tipo de comportamiento inesperado ocurre solo en el primer dibujo con el tipo de letra. Después de eso, todo funciona bien.
¿Es el comportamiento estándar o algo así?
Gracias.
PD: A continuación se muestra el código fuente del caso de prueba.
<!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>
Respuestas:
El dibujo en lienzo tiene que suceder y regresar inmediatamente cuando llama al
fillText
método. Sin embargo, el navegador aún no ha cargado la fuente de la red, lo cual es una tarea en segundo plano. Así que tiene que caer de nuevo a la fuente que no tenga disponible.Si desea asegurarse de que la fuente esté disponible, cargue algún otro elemento en la página, por ejemplo:
fuente
display: none
, pero eso puede hacer que los navegadores omitan la carga de la fuente. Es mejor usar un espacio en lugar de un.
.Utilice este truco y vincule un
onerror
evento a unImage
elemento.Demostración aquí : funciona en la última versión de Chrome.
fuente
src
atributo esté configurado, la carga comenzará en el siguiente bloque de ejecución.El meollo del problema es que está intentando utilizar la fuente pero el navegador aún no la ha cargado y posiblemente ni siquiera la haya solicitado. Lo que necesita es algo que cargue la fuente y le devuelva la llamada una vez que esté cargada; una vez que reciba la devolución de llamada, sabrá que está bien usar la fuente.
Mire WebFont Loader de Google ; parece un proveedor "personalizado" y una
active
devolución de llamada después de la carga lo haría funcionar.Nunca lo había usado antes, pero a partir de un escaneo rápido de los documentos, necesita hacer un archivo css
fonts/pressstart2p.css
, como este:Luego agregue el siguiente JS:
fuente
Puede cargar fuentes con la API FontFace antes de usarlas en el lienzo:
myfont.woff2
Primero se descarga el recurso de fuente . Una vez que se completa la descarga, la fuente se agrega al FontFaceSet del documento .La especificación de la API de FontFace es un borrador de trabajo en el momento de escribir este artículo. Consulte la tabla de compatibilidad de navegadores aquí.
fuente
document.fonts.add
. Vea la respuesta de bruno.¿Qué hay de usar CSS simple para ocultar un div usando una fuente como esta?
CSS:
HTML:
fuente
https://drafts.csswg.org/css-font-loading/
fuente
me encontré con el problema al jugar con él recientemente http://people.opera.com/patrickl/experiments/canvas/scroller/
lo solucionó agregando la familia de fuentes al lienzo directamente en el CSS, por lo que puede agregar
lienzo {familia de fuentes: PressStart; }
fuente
No estoy seguro de si esto te ayudará, pero para resolver el problema con mi código, simplemente creé un bucle for en la parte superior de mi Javascript que pasaba por todas las fuentes que quería cargar. Luego ejecuté una función para borrar el lienzo y precargar los elementos que quería en el lienzo. Hasta ahora ha funcionado perfectamente. Esa fue mi lógica, he publicado mi código a continuación:
fuente
Escribí un jsfiddle incorporando la mayoría de las correcciones sugeridas aquí, pero ninguna resolvió el problema. Sin embargo, soy un programador novato, por lo que tal vez no codifiqué las correcciones sugeridas correctamente:
http://jsfiddle.net/HatHead/GcxQ9/23/
HTML:
CSS:
JS:
Solución alterna Finalmente cedí y, en la primera carga, usé una imagen del texto mientras también colocaba el texto con las fuentes fuera del área de visualización del lienzo. Todas las visualizaciones posteriores de las fuentes dentro del área de visualización del lienzo funcionaron sin problemas. Esta no es una solución elegante de ninguna manera.
La solución está integrada en mi sitio web, pero si alguien la necesita, intentaré crear un jsfiddle para demostrarlo.
fuente
Algunos navegadores admiten la especificación de carga de fuentes CSS . Le permite registrar una devolución de llamada para cuando se hayan cargado todas las fuentes. Puede retrasar el dibujo de su lienzo (o al menos dibujar texto en su lienzo) hasta entonces y activar un nuevo dibujo una vez que la fuente esté disponible.
fuente
En primer lugar, use el cargador de fuentes web de Google como se recomienda en la otra respuesta y agregue su código de dibujo a la devolución de llamada que proporciona para indicar que las fuentes se han cargado. Sin embargo, este no es el final de la historia. Desde este punto, depende mucho del navegador. La mayoría de las veces funcionará bien, pero a veces puede ser necesario esperar unos cientos de milisegundos o usar las fuentes en otro lugar de la página. Probé diferentes opciones y el único método que afaik siempre funciona es dibujar rápidamente algunos mensajes de prueba en el lienzo con la familia de fuentes y las combinaciones de tamaño de fuente que vas a usar. Puedes hacerlo con el mismo color que el fondo, por lo que ni siquiera serán visibles y sucederá muy rápido. Después de eso, las fuentes siempre funcionaron para mí y en todos los navegadores.
fuente
Mi respuesta aborda las fuentes web de Google en lugar de @ font-face. Busqué por todas partes una solución al problema de la fuente que no aparecía en el lienzo. Probé temporizadores, setInterval, bibliotecas de retardo de fuentes y todo tipo de trucos. Nada funcionó. (Incluyendo poner font-family en el CSS para el lienzo o el ID del elemento del lienzo).
Sin embargo, descubrí que la animación de texto renderizado en una fuente de Google funcionaba fácilmente. ¿Cual es la diferencia? En la animación de lienzo, volvemos a dibujar los elementos animados una y otra vez. Entonces tuve la idea de renderizar el texto dos veces.
Eso tampoco funcionó, hasta que también agregué un breve retardo de temporizador (100 ms). Solo lo he probado en una Mac hasta ahora. Chrome funcionó bien a 100 ms. Safari requirió una recarga de página, así que aumenté el temporizador a 1000, y luego estuvo bien. Firefox 18.0.2 y 20.0 no cargarían nada en el lienzo si estuviera usando fuentes de Google (incluida la versión de animación).
Código completo: http://www.macloo.com/examples/canvas/canvas10.html
http://www.macloo.com/examples/canvas/scripts/canvas10.js
fuente
Se enfrenta al mismo problema. Después de leer "bobince" y otros comentarios, utilizo el siguiente javascript para solucionarlo:
fuente
Si desea volver a dibujar cada vez que se carga una nueva fuente (y probablemente cambiar la representación), la API de carga de fuentes también tiene un buen evento para eso. Tuve problemas con la Promesa en un entorno completamente dinámico.
fuente
El lienzo se dibuja independientemente de la carga DOM. La técnica de precarga solo funcionará si el lienzo se dibuja después de la precarga.
Mi solución, aunque no sea la mejor:
CSS:
HTML:
JavaScript:
fuente
Intento usar FontFaceSet.load para solucionar el problema: https://jsfiddle.net/wengshenshun/gr1zkvtq/30
Puede encontrar la compatibilidad del navegador en https://developer.mozilla.org/en-US/docs/Web/API/FontFaceSet/load
fuente
Este artículo resolvió mis problemas con las fuentes cargadas de forma diferida que no se mostraban.
Cómo cargar fuentes web para evitar problemas de rendimiento y acelerar la carga de la página
Esto me ayudó ...
fuente
Agregue un retraso como se muestra a continuación
fuente