Webフォント、HTML5Canvasで使うときの注意^^

Webフォントを使うと、ブラウザやOSが違っても同じ文字表現が出来るので便利だ。

だけど、結構な大きさのファイルをダウンロードさせる必要があるため(10MByte以上)中々導入となると、ちょっとねえ・・って二の足を踏んでしまう。

なので、これまであまりWebフォントを使わずに、なるべく内部のフォントを使っていたわけだが、今回ios,android,pcでそれぞれ表現させると、内部のフォントが結構ちがっていたこと、Webフォントを使うと、結構かっこよく見えたため、今回はWebフォントを採用しようと思った次第。

・・・・・・・・・・・・・・・・・・・・・・・

だけど、問題が勃発。

と言うのも、Canvasを使っている部分が主であり、このWebフォントをCanvasで利用したいと思っていたのだけど、画面を表示させたしょっぱなだけ、何故かWebフォントが使われないと言う、問題が発生していた。

と言うのも、PCでは普通に問題なく動くことから、発見が遅れたと言うか、実際にiosの実機でMobileSafariから起動させると、Canvasに対して、最初の表示文字がWebフォントを使われず、次に表示されるときからWebフォントが対応されると言う状況が発生したわけで、最初?何だろうか?画面がおかしいって感じで思った次第。

・・・・・・

結果論から言うと、CanvasでWebフォントを読もうとすると、非同期で実行されるため、だからCanvasの最初の表示では、文字に対してWebフォントは利用できない状況となり、内部のフォントが利用されていたと言うことである。

たぶん別途最初にCanvas上に対象のフォントを読み込み処理すれば、問題なくWebフォントが反映されると思うが、もっと簡単に対応できるものはないのか?って思い探したが、まあそんなものはなく、結果的に以下URLのサイトを参考に作った次第。

defghi1977-onblog.blogspot.jp

var ERROR_COUNT = 100;
var CHECK_TIME = 50;

// 指定されたWebフォントをCanvas向けにロード.
var loadWebFont = function(name,bold,successCall,errorCall) {
    
    //webフォントのロード状況を確認する
    var c1 = document.createElement("canvas");
    var c2 = c1.cloneNode(false);
    var ctx1 = c1.getContext("2d");
    var ctx2 = c2.getContext("2d");
    
    var boldText = (bold?"bold ":"");
    ctx1.font = " " + boldText + "15px "+name+", serif";
    ctx2.font = " " + boldText + "15px serif";
    
    var text = "load web font test.";
    
    //テキスト幅を比較する
    //webフォントが利用可能となると,フォント幅が一致する.
    var isLoaded = function(){
        var tm1 = ctx1.measureText(text);
        var tm2 = ctx2.measureText(text);
        return tm1.width != tm2.width;
    }
    
    var exitLoad 
    var cnt = 0;
    var tryDraw = function(){
        if(!isLoaded() && cnt < ERROR_COUNT){
            cnt++;
            setTimeout(tryDraw, CHECK_TIME);
        } else if(cnt >= ERROR_COUNT) {
            if(typeof(errorCall) == "function") {
                
                errorCall();
            }
        } else {
            if(typeof(successCall) == "function") {
                
                successCall();
            }
        }
    }
    tryDraw();
}

// Webフォント読み込み成功処理.
var viewSuccessWebFont = function(name,bold) {
    var canvas = document.createElement("canvas");
    var ctx = canvas.getContext("2d");
    ctx.fillStyle = "white";
    var boldText = (bold?"bold ":"");
    ctx.font = " " + boldText + "15px "+name+", serif";
    ctx.fillText(" ... success", 0, 0);
    document.body.appendChild(canvas);
}

// こんな感じで利用する。
loadWebFont("\'Noto Sans JP\'",true,function() {
    // WebFont読み込み成功.
    viewSuccessWebFont("\'Noto Sans JP\'",true);
});