ネットワークフォントのロードが完了すると通知されます

3140 ワード

Webページでカスタムフォントを使用するには、一般的に次のコードを使用します.
@font-face {
  font-family: 'myfont';
  src: url('font/MahjongTile/MahjongTile.eot');
  /* IE9 Compat Modes */
  src: url('font/MahjongTile/MahjongTile.eot?#iefix') format('embedded-opentype'),
  /* IE6-IE8 */
  url('font/MahjongTile/MahjongTile.woff2') format('woff2'),
  /* Super Modern Browsers */
  url('font/MahjongTile/MahjongTile.woff') format('woff'),
  /* Pretty Modern Browsers */
  url('font/MahjongTile/MahjongTile.ttf') format('truetype'),
  /* Safari, Android, iOS */
  url('font/MahjongTile/MahjongTile.svg#svgFontName') format('svg');
  /* Legacy iOS */
}

実際の環境ではよく現象に遭遇します.ページのDOMロードが完了すると、フォントファイルがまだロードされていないためです.カスタムフォントを使用するテキストブラウザはデフォルトのフォントで表示され、フォントファイルのロードが完了すると自動的にフォントがリフレッシュされます.これにより、ページのフォントに明らかなジャンプが変化します.
このような効果を回避するために、フォントファイルのロードが完了した場合にレスポンスのDOMが描画され、そうでなければページにコンテンツが表示されないか、ロード状態が描画されないと判断したい.では、コードはどのようにしてフォントがロードされたことを知っていますか?
方法一、FontFaceSet
「CSS Font Loading Module Level 3」仕様では、フォントを管理するためのインタフェースのセットが定義されています.コードを直接付けましょう.
fontWatcher=new Promise((resolve)=>{
  document.fonts.onloadingdone=(event) => {
    event.target.forEach((font) => {
      if (font.family === 'myfont' && font.status === 'loaded') {
        resolve(font);
      }
    });
  };
});

fontWatcher.then((font)=>{
  console.log(`${font.family}      `);
});

フォント幅の比較
この仕様がまだサポートされていないブラウザでは、同じ文字にデフォルトフォントとカスタムフォントをそれぞれ付与することを考えています.幅が一致している場合は、カスタムフォントがまだロードされていないと判断し、一致しない場合はロードが完了していると判断します.この考え方はGoogleの「webfontloader」を学んでまとめたものです.
const fn_fontWatch=(fontFamily)=>{
  const fn_gen_span_with_font=(font)=>{
    const span=document.createElement('span');
span.style.cssText=`display:block;position:absolute;top:-9999px;left:-9999px;
font-size:300px;width:auto;height:auto;line-height:normal;margin:0;
padding:0;font-variant:normal;white-space:nowrap;font-family:${font}`;
    span.innerHTML='BESbswy';
    document.body.append(span);
    return span;
  };
  const font_serif=['serif','sans_serif']
  const default_width=[];
  const font_span=[];
  font_serif.forEach((font)=>{
    const span_default=fn_gen_span_with_font(font);
    default_width.push(span_default.offsetWidth);
    document.body.removeChild(span_default);
    const span_font=fn_gen_span_with_font(`${fontFamily},${font}`);
    font_span.push(span_font);
  });
  return new Promise((resolve)=>{
    const fn_check=()=>{
      let ret=false;
      for(let i=0;i{
      if(fn_check()){
        font_span.forEach((span)=>{
          document.body.removeChild(span);
        });
        resolve(fontFamily);
      }else{
        window.setTimeout(fn_check_loop,10);
      }
    };
    fn_check_loop();
  });
};

fontWatcher=fn_fontWatch('myfont');
fontWatcher.then((font)=>{
  console.log(`${font.family}      `);
});