gazou-compressor.jp

AVIF 大判画像タイル戦略:遅延分割/LOD/視点適応ロードの実装

巨大な製品画像/地図/年表をモバイルで一括ロードすると 初期LCP/メモリ/帯域 が肥大化します。タイル+LODは "見える所だけ" を逐次供給しUXを維持する定番戦略です。

構成要素
  • タイル分割 (512/1024)
  • LOD階層 (1x/2x/4x例)
  • ビューポート/ズームで差し替え
  • 初期軽量プレビュー (LQ AVIF)

1. 目的

初期ビューで 体感応答 を維持しながら詳細要求時のみ高解像度取得。帯域節約とINP劣化回避に寄与します。

2. タイル生成

# 1. タイル分割 (Sharp例)
sharp poster.png \
  .tile({ size: 512, layout: 'dz' }) \
  .toFile('out');
// 2. manifest.json (抜粋)
{
  "+0": { "w":512, "h":512, "tiles": [[0,0],[1,0],[2,0],[3,0]] },
  "+1": { "w":1024, "h":1024, "tiles": [[0,0],[1,0],[2,0],[3,0]] }
}

3. LOD階層

// 4. ズームレベル -> 階層選択
function level(scale){
  if (scale < 1.3) return 0;
  if (scale < 2.1) return 1;
  return 2;
}

4. ビューポート適応ロード

// 3. ビューポート適応ロード (pseudo)
const obs = new IntersectionObserver(entries=>{
  for (const e of entries){
    if (e.isIntersecting) loadTile(e.target.dataset.src);
  }
},{ root: viewportEl, rootMargin:'256px' });

5. 実装詳細 (優先度/メモリ)

視点中心から曼荼羅状に 曼延優先ロード することで初期パン時の “未解像タイル” 発生を抑制。Priority Hints(fetchpriority) で中心列を high、周辺は low。

// 優先ロード (中心→周辺)
function sortTiles(tiles, center){
  return tiles.sort((a,b)=>dist(a,center)-dist(b,center));
}

ビューポート外タイルは 最後の参照時刻 を記録し猶予後に revoke しメモリ回収。GPUテクスチャ保持実装では VRAM 枯渇防止に必須。

// メモリ解放 (一定時間未参照タイルを撤去)
const LIVE = new Map(); // key -> { lastSeen, url }
setInterval(()=>{
  const now = performance.now();
  for (const [k,v] of LIVE){
    if (now - v.lastSeen > 12000){
      URL.revokeObjectURL(v.url);
      LIVE.delete(k);
    }
  }
},4000);

6. 性能計測/ベンチ

# ネットワーク計測 (Chromium Trace -> tiles.json 抽出)
node scripts/extract-tiles-trace.js trace.json > tiles.json
jq '.tiles | group_by(.priority) | map({p:.[0].priority, sum: (map(.bytes)|add)})' tiles.json

7. 運用/監視

総タイル数 / 初期bytes / ズーム切替遅延を継続監視し LOD 設計のドリフトを防止。Prometheus exporter で level 別 bytes を集計し週次トレンド化。

# Grafana メトリクス例 (PromQL)
rate(tile_bytes_total[5m]) by (level)
quantile(0.95, sum(rate(tile_latency_ms_bucket[5m])) by (le,level))

8. 失敗パターン

9. CI/回帰検知

# CI: 初期ロードbytes上限 & タイル総数回帰検知
node scripts/tiles-metrics.js poster.manifest.json --max-initial-bytes 450000 --max-tiles 160

初期表示bytesの安定は CIパイプライン に統合し監視します。

10. FAQ

11. まとめ

タイル+LOD+視点適応ロードで巨大画像の “必要な部分だけ高解像度” を満たし、全体一括より帯域 40–70% 削減が現実的に狙えます。

gazou-compressor.jp 編集部

画像圧縮・変換・背景除去などの実践テクニックと、Webで“速く・軽く・崩さない”ためのノウハウを発信しています。

関連記事

トピック/更新日の近いコンテンツ