Рисование текста до <canvas>с помощью @ font-face не работает в первый раз - PullRequest
82 голосов
/ 03 мая 2010

Когда я рисую текст на холсте с гарнитурой, загруженной через @ font-face, текст отображается неправильно. Он вообще не отображается (в Chrome 13 и Firefox 5), или неправильный шрифт (Opera 11). Этот тип неожиданного поведения происходит только на первом рисунке с гарнитурой. После этого все работает нормально.

Это стандартное поведение или что-то?

Спасибо.

PS: ниже приведен исходный код контрольного примера

<code><!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>@font-face and &lt;canvas&gt;</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 &lt;canvas&gt;</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">

Сценарий

 
var x = 30, у = 10; $ ('# draw'). click (function () { var canvas = $ ('canvas') [0], ctx = canvas.getContext ('2d'); ctx.font = '12px "Нажмите Start 2P"'; ctx.fillStyle = '# 000'; ctx.fillText («Привет, мир!», x, y + = 20); ctx.fillRect (x - 20, y - 10, 10, 10); }); $ ( '# Показов CSS') текст ($ ( '# CSS') текст ().). $ ( '# Вид-скрипт') текст ($ ( '# скрипт') текст ().).

Ответы [ 17 ]

0 голосов
/ 05 декабря 2018

Я пытаюсь использовать FontFaceSet.load для решения проблемы: https://jsfiddle.net/wengshenshun/gr1zkvtq/30

const prepareFontLoad = (fontList) => Promise.all(fontList.map(font => document.fonts.load(font)))

Вы можете найти совместимость браузера с https://developer.mozilla.org/en-US/docs/Web/API/FontFaceSet/load

0 голосов
/ 24 марта 2018

Холст рисуется независимо от загрузки DOM. Техника предварительной загрузки будет работать, только если холст будет нарисован после предварительной загрузки.

Мое решение, даже если оно не самое лучшее:

CSS:

.preloadFont {
    font-family: 'Audiowide', Impact, Charcoal, sans-serif, cursive;
    font-size: 0;
    position: absolute;
    visibility: hidden;
}

HTML:

<body onload="init()">
  <div class="preloadFont">.</div>
  <canvas id="yourCanvas"></canvas>
</body>

JavaScript:

function init() {
    myCanvas.draw();
}
0 голосов
/ 01 декабря 2017

Если вы хотите перерисовывать каждый раз, когда загружается новый шрифт (и, возможно, изменить рендеринг), в api загрузки шрифта есть хорошее событие для этого тоже. У меня были проблемы с Promise в полной динамической среде.

var fontFaceSet = document.fonts;
if (fontFaceSet && fontFaceSet.addEventListener) {
    fontFaceSet.addEventListener('loadingdone', function () {
        // Redraw something

    });
} else {
    // no fallback is possible without this API as a font files download can be triggered
    // at any time when a new glyph is rendered on screen
}
0 голосов
/ 05 ноября 2011

Прежде всего используйте загрузчик веб-шрифтов Google, как было рекомендовано в другом ответе, и добавьте свой код рисования в ответный вызов, который он предоставляет, чтобы указать, что шрифты были загружены. Однако это не конец истории. С этой точки зрения это очень зависит от браузера. Большую часть времени он будет работать нормально, но иногда может потребоваться подождать пару сотен миллисекунд или использовать шрифты где-то еще на странице. Я пробовал разные варианты, и один из методов, который всегда работает afaik, - это быстро нарисовать на холсте несколько тестовых сообщений с семейством шрифтов и комбинациями размеров шрифта, которые вы собираетесь использовать. Вы можете сделать это с тем же цветом, что и фон, так что они даже не будут видны, и это произойдет очень быстро. После этого у меня и во всех браузерах всегда работали шрифты.

0 голосов
/ 29 июля 2012

сталкивается с той же проблемой. Прочитав «bobince» и другие комментарии, я использую следующий javascript, чтобы обойти это:

$('body').append("<div id='loadfont' style='font-family: myfont;'>.</div>");
$('#loadfont').remove();
0 голосов
/ 03 ноября 2015

Добавьте задержку, как показано ниже

<script>
var c = document.getElementById('myCanvas');    
var ctx = c.getContext('2d');
setTimeout(function() {
    ctx.font = "24px 'Proxy6'"; // uninstalled @fontface font style 
    ctx.textBaseline = 'top';
    ctx.fillText('What!', 20, 10);      
}, 100); 
</script>
0 голосов
/ 01 мая 2013

Мой ответ касается веб-шрифтов Google, а не @ font-face. Я искал повсюду решение проблемы шрифта, не появляющегося на холсте. Я пробовал таймеры, setInterval, библиотеки с задержкой шрифтов и всевозможные трюки. Ничего не получалось. (Включая размещение font-family в CSS для canvas или ID элемента canvas.)

Однако я обнаружил, что анимация текста, отображаемого шрифтом Google, работает легко. Какая разница? В анимации холста мы снова и снова рисуем анимированные элементы. Таким образом, у меня появилась идея визуализировать текст дважды.

Это тоже не работало - пока я не добавил короткую (100 мс) задержку таймера. Я пока тестировал только на Mac. Хром работал нормально на 100мс. Safari потребовал перезагрузки страницы, поэтому я увеличил таймер до 1000, и тогда все было в порядке. Firefox 18.0.2 и 20.0 не загружали бы что-либо на холст, если бы я использовал шрифты Google (включая версию анимации).

Полный код: http://www.macloo.com/examples/canvas/canvas10.html

http://www.macloo.com/examples/canvas/scripts/canvas10.js

...