[html] 처음에 @ font-face를 사용하여 <canvas>에 텍스트 그리기가 작동하지 않습니다.

@ font-face를 통해로드 된 서체로 캔버스에 텍스트를 그릴 때 텍스트가 올바르게 표시되지 않습니다. 전혀 표시되지 않거나 (Chrome 13 및 Firefox 5에서) 서체가 잘못되었습니다 (Opera 11). 이러한 유형의 예기치 않은 동작은 서체가있는 첫 번째 드로잉에서만 발생합니다. 그 후 모든 것이 잘 작동합니다.

표준 행동입니까?

감사합니다.

추신 : 다음은 테스트 케이스의 소스 코드입니다.

<!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"></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>



답변

캔버스에 그리기가 일어나야하고 fillText메서드 를 호출하면 즉시 돌아와야합니다 . 그러나 브라우저는 아직 백그라운드 작업 인 네트워크에서 글꼴을로드하지 않았습니다. 이 글꼴로 후퇴하는 그래서 않습니다 사용할 수 있습니다.

글꼴을 사용할 수 있는지 확인하려면 페이지에 다른 요소를 미리로드하십시오. 예 :

<div style="font-family: PressStart;">.</div>


답변

이 트릭을 사용 하여 onerror이벤트를 Image요소에 바인딩 하십시오 .

여기 데모 : 최신 Chrome에서 작동합니다.

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

var link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = 'http://fonts.googleapis.com/css?family=Vast+Shadow';
document.getElementsByTagName('head')[0].appendChild(link);

// Trick from /programming/2635814/
var image = new Image();
image.src = link.href;
image.onerror = function() {
    ctx.font = '50px "Vast Shadow"';
    ctx.textBaseline = 'top';
    ctx.fillText('Hello!', 20, 10);
};


답변

문제의 핵심은 글꼴을 사용하려고하지만 브라우저가 글꼴을 아직로드하지 않았으며 요청하지 않았을 수도 있다는 것입니다. 필요한 것은 글꼴을로드하고로드 된 후 콜백을 제공하는 것입니다. 콜백을 받으면 글꼴을 사용해도된다는 것을 알 수 있습니다.

Google의 WebFont Loader를보십시오 . “맞춤형”제공 업체와active 로드 후 콜백이 작동하도록합니다.

나는 전에 그것을 사용한 적이 없지만 문서의 빠른 스캔에서 다음 fonts/pressstart2p.css과 같이 css 파일을 만들어야합니다 .

@font-face {
  font-family: 'Press Start 2P';
  font-style: normal;
  font-weight: normal;
  src: local('Press Start 2P'), url('http://lemon-factory.net/reproduce/fonts/Press Start 2P.ttf') format('ttf');
}

그런 다음 다음 JS를 추가하십시오.

  WebFontConfig = {
    custom: { families: ['Press Start 2P'],
              urls: [ 'http://lemon-factory.net/reproduce/fonts/pressstart2p.css']},
    active: function() {
      /* code to execute once all font families are loaded */
      console.log(" I sure hope my font is loaded now. ");
    }
  };
  (function() {
    var wf = document.createElement('script');
    wf.src = ('https:' == document.location.protocol ? 'https' : 'http') +
        '://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
    wf.type = 'text/javascript';
    wf.async = 'true';
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(wf, s);
  })();


답변

캔버스에서 사용하기 전에 FontFace API로 글꼴을로드 할 수 있습니다 .

const myFont = new FontFace('My Font', 'url(https://myfont.woff2)');

myFont.load().then((font) => {
  document.fonts.add(font);

  console.log('Font loaded');
});

글꼴 리소스 myfont.woff2가 먼저 다운로드됩니다. 다운로드가 완료되면 글꼴이 문서의 FontFaceSet에 추가됩니다 .

FontFace API의 사양은이 글을 쓰는 시점의 작업 초안입니다. 여기에서 브라우저 호환성 표를 참조하십시오.


답변

간단한 CSS를 사용하여 다음과 같은 글꼴을 사용하여 div를 숨기는 것은 어떻습니까?

CSS :

#preloadfont {
  font-family: YourFont;
  opacity:0;
  height:0;
  width:0;
  display:inline-block;
}

HTML :

<body>
   <div id="preloadfont">.</div>
   <canvas id="yourcanvas"></canvas>
   ...
</body>


답변

https://drafts.csswg.org/css-font-loading/

var myFont = new FontFace('My Font', 'url(https://myfont.woff2)');

myFont.load().then(function(font){

  // with canvas, if this is ommited won't work
  document.fonts.add(font);

  console.log('Font loaded');

});


답변

나는 최근에 그것을 가지고 놀 때 문제에 부딪쳤다. http://people.opera.com/patrickl/experiments/canvas/scroller/

CSS에서 직접 캔버스에 font-family를 추가하여 문제를 해결했습니다.

canvas {font-family : PressStart; }