browser/gameplaybook PC / MOBILE · INTERACTIVE GUIDE 画像共有デモ
BROWSER GAME / IMPLEMENTATION GUIDE10 PATTERNS · 01 COLLECTION

ゲームの操作を、
ブラウザに邪魔させない。

ダブルタップで画面が拡大する。ドラッグ中にスクロールする。復帰時にキャラが飛ぶ。
そうしたWebゲーム特有の問題を、再現・改善・実装の順に確認できるリファレンスです。

実際に試す
LIVE EXAMPLES試す → 仕組みを確認する
01TOUCH / ZOOM

ダブルタップで拡大される

連打するゲーム操作に、ブラウザのズームが割り込まないようにする。touch-action: manipulation はダブルタップ拡大を抑え、通常のピンチ拡大は残します。

タップ操作の比較
ダブルタップ拡大を抑制実際のズームの発生は、ブラウザ・端末設定に依存します。
推奨コードを表示
.game-button { touch-action: manipulation; }
/* 全体に user-scalable=no を指定しない。 */
02TOUCH / SCROLL

操作中にページまでスクロールする

ゲーム面のスワイプはゲームに使い、メニュー内のスクロールは残す。親ページへスクロールが伝播することも防ぎます。

内側を上下にスクロール
ITEM 01 ステータス
ITEM 02 装備一覧
ITEM 03 スキル
ITEM 04 アイテム
ITEM 05 ミッション
ITEM 06 図鑑
ITEM 07 セーブ

スクロールが端に達しても、親のページへ伝わりにくくなります。

推奨コードを表示
.game-canvas { touch-action: none; }
.game-controls { touch-action: manipulation; }
.game-scroll { overflow: auto; overscroll-behavior: contain; }
03TOUCH / SELECTION

長押しで文字選択・メニューが出る

戦闘ボタンやCanvasでは不要な選択を抑えつつ、文章・入力欄は選択可能にする。ページ全体を禁止しない。

長押し・ドラッグして比較
ATTACK × 2
ゲーム用の操作対象

これは普通の説明文。長押しで選択・コピーできます。

文章は選択可能

操作対象だけ選択を無効化しています。

推奨コードを表示
.game-control {
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}
/* input, textarea, 説明文には適用しない */
04INPUT / POINTER

ドラッグの途中で操作を失う

指がオブジェクトの外へ出ても追跡し、キャンセル時には操作を終了する。マウスとタッチをPointer Eventsで扱います。

丸い駒をドラッグ待機中
✧
POINTER CAPTURE ACTIVE

駒の外まで指を動かしてから離しても、入力が終了します。

推奨コードを表示
token.addEventListener('pointerdown', e => {
  token.setPointerCapture(e.pointerId);
});
token.addEventListener('pointermove', moveWhenActive);
token.addEventListener('pointerup', stop);
token.addEventListener('pointercancel', stop);
token.addEventListener('lostpointercapture', stop);
05LAYOUT / VIEWPORT

アドレスバーやノッチで画面が見切れる

画面の高さを固定値にせず、動的な表示領域とセーフエリアに合わせる。縦画面・横画面どちらでも余白が必要です。

この端末の表示領域計測中
window.innerHeight—
100vh—
100dvh—
上部の操作領域
GAME AREA
下部UI safe area

ブラウザのバーを表示・非表示にして値の変化を比較できます。

推奨コードを表示
<meta name="viewport"
 content="width=device-width, initial-scale=1, viewport-fit=cover">
.game-shell { min-height: 100dvh; }
.game-hud {
  padding-bottom: env(safe-area-inset-bottom, 0px);
  padding-inline:
    env(safe-area-inset-left, 0px)
    env(safe-area-inset-right, 0px);
}
06AUDIO / AUTOPLAY

最初の効果音が鳴らない

Web Audioは再生前にユーザー操作が必要なことがあります。スタート操作でAudioContextを有効化し、無音状態を見えるようにします。

短い効果音を鳴らす未開始

クリック・タップしてから初めて音を鳴らします。ページ読み込み時には再生しません。

推奨コードを表示
startButton.addEventListener('click', () => {
  audioContext ??= new AudioContext();
  audioContext.resume(); // ユーザー操作から実行
});
07LIFECYCLE / PAUSE

別タブから戻るとゲームが飛ぶ

非表示中は進行を止め、復帰後はプレイヤーが再開するまで止めておく。RAFの経過時間も上限を決めます。

ゲーム内タイマー停止中
00.0SEC

開始後に別タブへ移動すると自動で一時停止します。戻っても勝手には再開しません。

推奨コードを表示
document.addEventListener('visibilitychange', () => {
  if (document.hidden) pauseGame();
});
function tick(now) {
  const dt = Math.min(now - previousTime, 50);
  updateGame(dt);
  requestAnimationFrame(tick);
}
08RENDER / CANVAS

Canvasがぼやける、描画が重い

CanvasのCSS表示サイズと内部解像度を合わせる。端末DPRを無制限に採用せず、ゲームの画風・負荷に合わせて上限を決めます。

描画解像度の比較
—描画バッファの大きさ—

ドット絵の場合はアンチエイリアスの有無も含め、実ゲーム画面の見た目で判断します。

推奨コードを表示
const rect = canvas.getBoundingClientRect();
const dpr = Math.min(devicePixelRatio || 1, 2);
canvas.width = Math.round(rect.width * dpr);
canvas.height = Math.round(rect.height * dpr);
const ctx = canvas.getContext('2d');
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
ctx.imageSmoothingEnabled = false; // ドット絵の場合
09LAYOUT / FULLSCREEN

全画面・回転でレイアウトが崩れる

全画面はユーザー操作から要求し、未対応や拒否を扱う。スマホを回した際は、固定サイズではなく現在の幅・高さを読んで配置を更新します。

全画面を切り替える確認中
VIEWPORT / —

全画面の可否はブラウザによって異なります。画面方向の固定は要求しません。

推奨コードを表示
try {
  await gameElement.requestFullscreen(); // ユーザー操作直後
} catch {
  showNormalLayout(); // 非対応・拒否でもプレイ可能に
}
window.addEventListener('resize', relayout);
10RESULT / SHARING

結果画像をうまく共有できない

ゲーム画面のスクリーンショットではなく、共有専用の画像を生成。ネイティブ共有・PNGコピー・保存を機能に応じて提供します。

IMPLEMENTATION POLICY

ブラウザの操作を全部止めるのではなく、
ゲームに必要な領域だけ制御する。

ズーム、テキスト選択、スクロールは通常のWebページでは重要な機能です。ゲーム操作面と説明・入力欄を分けることで、操作ミスを抑えながら使いやすさを維持します。