scale-and-responsive について
Phaser 4 のスケーリングとレスポンシブレイアウトを解説する、ゲーム開発者向けのスキルガイドです。ScaleManager によるキャンバスのサイズ調整、中央配置、全画面表示、画面向きの変更、リサイズイベントを扱います。
主な機能
- 01キャンバスのスケーリングモード
- 02キャンバスの自動中央配置とズーム
- 03レスポンシブなリサイズとイベント
- 04全画面表示の切り替え
- 05画面向きの変更処理
活用シーン
- 01ゲームキャンバスを親要素に合わせる
- 02アスペクト比を保った中央配置
- 03ウィンドウのリサイズに応じたシーン調整
- 04モバイル端末の画面向き変更への対応
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ phaserjs/ phaser --skill scale-and-responsiveインストール後、Claude Code で/scale-and-responsiveを入力して読み込まれたか確認します。
詳細
スケーリングとレスポンシブデザイン
Phaser 4 でスケーリング、中央揃え、フルスクリーン、向きの処理、レスポンシブなリサイズに ScaleManager を使用する方法。
主要なソースパス: src/scale/ScaleManager.js、src/scale/const/、src/scale/events/、src/core/typedefs/ScaleConfig.js
関連スキル: ../game-setup-and-config/SKILL.md
クイックスタート
中央揃え付きのスケールトゥフィット -- レスポンシブゲームで最も一般的な設定です:
const config = {
type: Phaser.AUTO,
scale: {
parent: 'game-container',
mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_BOTH,
width: 800,
height: 600
},
scene: MyScene
};
const game = new Phaser.Game(config);
scale 設定オブジェクトは Phaser.Core.Config インスタンスに解析され、ScaleManager が起動時にそれを読み取ります。ScaleManager はキャンバス要素のサイズを設定し、親要素内に収まるように CSS スケーリングを適用します。
基本概念
ScaleManager (src/scale/ScaleManager.js)
ScaleManager は Game の起動シーケンス中に作成され、game.scale または Scene 内から this.scale でアクセスできます。EventEmitter を継承しています。
3 つの内部 Size コンポーネントがすべての計算を駆動します:
| コンポーネント | プロパティ | 目的 |
|---|---|---|
gameSize | game.scale.gameSize | 設定からの未変更のゲーム寸法。ワールド境界やカメラに使用されます。game.scale.width / game.scale.height で読み取ります。 |
baseSize | game.scale.baseSize | 自動で丸められた gameSize。実際の canvas.width および canvas.height 属性を設定します。 |
displaySize | game.scale.displaySize | スケールモード、親の境界、ズームを適用した後の CSS スケーリングされたキャンバスサイズ。canvas.style.width / canvas.style.height を設定します。 |
スケーリングは、キャンバス要素の寸法を固定したまま (baseSize)、CSS プロパティ (displaySize) で引き伸ばすことによって機能します。これは CSS の transform-scale と同等ですが、ブラウザのプレフィックスの問題がありません。
displayScale プロパティ (Phaser.Math.Vector2) は baseSize / canvasBounds の比率を保持し、内部的に入力座標の変換に使用されます。
スケールモード (src/scale/const/SCALE_MODE_CONST.js)
すべてのモードは Phaser.Scale.ScaleModes にあり、設定の scale.mode で設定します:
| 定数 | 値 | 動作 |
|---|---|---|
NONE | 0 | 自動スケーリングなし。キャンバスは設定の width/height を使用します。サイズ管理は自分で行います。外部でキャンバスのサイズを変更した場合は、game.scale.resize(w, h) を呼び出して内部を更新してください。 |
WIDTH_CONTROLS_HEIGHT | 1 | 幅に基づいてアスペクト比を維持するように高さが自動調整されます。 |
HEIGHT_CONTROLS_WIDTH | 2 | 高さに基づいてアスペクト比を維持するように幅が自動調整されます。 |
FIT | 3 | アスペクト比を維持しながら親要素内に収まるようにスケーリングします。空きスペースができる場合があります (レターボックス/ピラーボックス)。最も一般的に使用されるモードです。 |
ENVELOP | 4 | アスペクト比を維持しながら親要素全体を覆うようにスケーリングします。親の境界を超えて拡張する場合があります (コンテンツが切り取られます)。 |
RESIZE | 5 | キャンバス要素自体が親要素を埋めるようにリサイズされます。CSS スケーリングは行わず、1:1 のピクセルマッピングです。gameSize、baseSize、displaySize はすべて親要素に合わせて変化します。大型ディスプレイでは GPU のフィルレートに注意してください。 |
EXPAND | 6 | RESIZE と FIT のハイブリッドです。可視領域が親要素を埋めるようにリサイズされ、キャンバスはその領域内に収まるようにスケーリングされます。v3.80 で追加されました。 |
省略形の定数 は Phaser.Scale に直接用意されています: Phaser.Scale.FIT、Phaser.Scale.RESIZE など。
センターモード (src/scale/const/CENTER_CONST.js)
設定の scale.autoCenter で設定します。中央揃えは、キャンバスに CSS の marginLeft と marginTop を設定することによって実現されます:
| 定数 | 値 | 動作 |
|---|---|---|
NO_CENTER | 0 | 自動中央揃えなし (デフォルト)。 |
CENTER_BOTH | 1 | 親要素内で水平方向と垂直方向の両方に中央揃えします。 |
CENTER_HORIZONTALLY | 2 | 水平方向のみ中央揃えします。 |
CENTER_VERTICALLY | 3 | 垂直方向のみ中央揃えします。 |
親要素には計算可能な境界が必要です。親要素に幅/高さが定義されていない場合、中央揃えは正しく機能しません。
Zoom (src/scale/const/ZOOM_CONST.js)
設定では scale.zoom で設定します。表示サイズを乗算します:
| 定数 | 値 | 動作 |
|---|---|---|
NO_ZOOM | 1 | ズームなし(デフォルト)。 |
ZOOM_2X | 2 | 2倍ズーム -- 低いベース解像度のピクセルアートに適しています。 |
ZOOM_4X | 4 | 4倍ズーム。 |
MAX_ZOOM | -1 | 親要素に収まる最大の整数ズームを自動計算します。 |
任意の数値を渡すこともできます。ズームは CSS の表示サイズに影響しますが、キャンバスの解像度には影響しません。
Orientation (src/scale/const/ORIENTATION_CONST.js)
game.scale.orientation で読み取ります。値は文字列です:
Phaser.Scale.Orientation.LANDSCAPE='landscape-primary'Phaser.Scale.Orientation.LANDSCAPE_SECONDARY='landscape-secondary'Phaser.Scale.Orientation.PORTRAIT='portrait-primary'Phaser.Scale.Orientation.PORTRAIT_SECONDARY='portrait-secondary'
便利な真偽値: game.scale.isPortrait、game.scale.isLandscape(デバイスの向き)、game.scale.isGamePortrait、game.scale.isGameLandscape(ゲームの寸法)。
一般的なパターン
中央揃え付き FIT モード(最も一般的)
scale: {
parent: 'game-container',
mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_BOTH,
width: 1280,
height: 720
}
ゲームは 16:9 のアスペクト比を維持し、親要素内で中央に配置されます。空きスペースはレターボックス/ピラーボックスのバーとして表示されます。バーの見た目を制御するには、親要素の背景色をスタイル設定してください。
レスポンシブリサイズ(動的キャンバスサイズ)
scale: {
parent: 'game-container',
mode: Phaser.Scale.RESIZE,
width: '100%',
height: '100%'
}
// In your scene -- respond to size changes:
create() {
this.scale.on('resize', this.handleResize, this);
}
handleResize(gameSize, baseSize, displaySize) {
this.cameras.resize(gameSize.width, gameSize.height);
// Reposition UI elements based on new dimensions
}
width/height はパーセンテージ文字列(例: '100%')を受け付け、親要素のサイズに対して解決されます。親要素にサイズがない場合は、window.innerWidth / window.innerHeight にフォールバックします。
フルスクリーン切り替え
// Must be called from a pointerup gesture (not pointerdown)
this.input.on('pointerup', () => {
if (this.scale.isFullscreen) {
this.scale.stopFullscreen();
} else {
this.scale.startFullscreen();
}
});
// Or use the convenience method:
this.input.on('pointerup', () => {
this.scale.toggleFullscreen();
});
startFullscreen(fullscreenOptions)-- ブラウザのフルスクリーンを要求します。デフォルトのオプション:{ navigationUI: 'hide' }。stopFullscreen()-- フルスクリーンモードを終了します。toggleFullscreen(fullscreenOptions)-- 2つの間で切り替えます。isFullscreen-- 現在の状態を示す読み取り専用の真偽値。
fullscreenTarget が設定されていない場合、Phaser は一時的な <div> を作成し、キャンバスをその中に移動して、その div をフルスクリーンにします。フルスクリーンを終了すると div は削除されます。
iframe の場合、allowfullscreen 属性が必要です。
モバイルの向きの処理
create() {
this.scale.on('orientationchange', (orientation) => {
if (orientation === Phaser.Scale.LANDSCAPE) {
// Show game UI
} else {
// Show "rotate device" message
}
});
// Lock orientation (mobile browsers only, limited support):
this.scale.lockOrientation('landscape');
}
固定サイズ(スケーリングなし)
scale: {
mode: Phaser.Scale.NONE,
width: 800,
height: 600
}
NONE モードでは、外部でキャンバスサイズを変更する場合、入力座標を含むすべての内部コンポーネントを更新するために game.scale.resize(newWidth, newHeight) を呼び出す必要があります。
最大ズームを使ったピクセルアート
scale: {
mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_BOTH,
width: 320,
height: 240,
zoom: Phaser.Scale.MAX_ZOOM
},
pixelArt: true
MAX_ZOOM は親要素に収まる最大の整数倍率を計算します。pixelArt: true(アンチエイリアスを無効にする)と組み合わせることで、くっきりとしたピクセルレンダリングが得られます。
グリッド配置のためのスナップ値
scale: {
mode: Phaser.Scale.FIT,
width: 800,
height: 600,
snap: { width: 16, height: 16 }
}
ブラウザのリサイズ時に、寸法は最も近いグリッドの倍数に切り捨てられます(floor を使用)。FIT モードと併用するのが最適です。実行時に設定することもできます: game.scale.setSnap(16, 16)、または game.scale.setSnap() でリセットします。
最小/最大サイズの制約
scale: {
mode: Phaser.Scale.FIT,
width: 800,
height: 600,
min: { width: 400, height: 300 },
max: { width: 1600, height: 1200 }
}
表示サイズはスケーリング計算中にこれらの境界にクランプされます。
設定リファレンス
ScaleConfig (src/core/typedefs/ScaleConfig.js)
すべてのプロパティは、ゲーム設定の scale オブジェクト内に記述します:
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
width | number|string | 1024 | ベースとなるゲームの幅。'100%' のような文字列は親のサイズを基準に解決されます。 |
height | number|string | 768 | ベースとなるゲームの高さ。'100%' のような文字列は親のサイズを基準に解決されます。 |
zoom | number|ZoomType | 1 | キャンバスのズーム倍率。自動にするには Phaser.Scale.MAX_ZOOM を使用します。 |
parent | HTMLElement|string|null | undefined | 親 DOM 要素またはその ID。undefined = document.body。null = 親なし(キャンバスの配置は自身で管理します)。 |
expandParent | boolean | true | ScaleManager が親/body の CSS の高さを 100% に設定することを許可します。 |
mode | ScaleModeType | NONE | スケールモードの定数(上の表を参照)。 |
min | {width, height} | - | キャンバスの最小サイズ。 |
max | {width, height} | - | キャンバスの最大サイズ。 |
snap | {width, height} | - | リサイズ時の丸めに使用するスナップ値。 |
autoRound | boolean | false | 低スペックデバイスのパフォーマンスのために、表示/スタイルのサイズを切り捨てます。 |
autoCenter | CenterType | NO_CENTER | 自動センタリングモード(上の表を参照)。 |
resizeInterval | number | 500 | 親のサイズをチェックする間隔(ミリ秒、フォールバックのポーリング)。 |
fullscreenTarget | HTMLElement|string | undefined | フルスクリーンにする要素。設定しない場合、Phaser がラッパー div を作成します。 |
イベント (src/scale/events/)
すべてのイベントは Phaser.Scale.Events にあり、ScaleManager インスタンス(game.scale)によって発行されます:
| イベント | 文字列値 | コールバックシグネチャ | 発生タイミング |
|---|---|---|---|
RESIZE | 'resize' | (gameSize, baseSize, displaySize, previousWidth, previousHeight) | リサイズ、リフレッシュ、スケール変更のいずれか。3 つの Size パラメータには .width、.height、.aspectRatio があります。 |
ORIENTATION_CHANGE | 'orientationchange' | (orientation) | デバイスの向きが変わったとき。orientation は Phaser.Scale.Orientation の文字列定数です。 |
ENTER_FULLSCREEN | 'enterfullscreen' | () | ブラウザがフルスクリーンへの移行に成功したとき。 |
LEAVE_FULLSCREEN | 'leavefullscreen' | () | ブラウザがフルスクリーンを終了したとき(コードまたはユーザーの ESC による)。 |
FULLSCREEN_FAILED | 'fullscreenfailed' | (error) | フルスクリーンのリクエストがブラウザによって拒否されたとき。 |
FULLSCREEN_UNSUPPORTED | 'fullscreenunsupported' | () | ブラウザが Fullscreen API をサポートしていないとき。 |
API クイックリファレンス
主要なプロパティ(注記がない限り読み取り専用)
| プロパティ | 型 | 説明 |
|---|---|---|
width | number | ゲームの幅(gameSize.width から取得)。 |
height | number | ゲームの高さ(gameSize.height から取得)。 |
isFullscreen | boolean | 現在フルスクリーンモードであるか。 |
isPortrait | boolean | デバイスが縦向きであるか。 |
isLandscape | boolean | デバイスが横向きであるか。 |
isGamePortrait | boolean | ゲームの寸法が横より縦に長いか。 |
isGameLandscape | boolean | ゲームの寸法が縦より横に長いか。 |
scaleMode | number | 現在のスケールモード定数。 |
orientation | string | 現在の向きを表す文字列。 |
zoom | number | 現在のズーム倍率。 |
autoRound | boolean | サイズが自動的に切り捨てられるかどうか。 |
autoCenter | number | 現在のセンターモード定数。 |
parentSize | Size | 計算された親要素の寸法。 |
gameSize | Size | 未変更のゲームの寸法。 |
baseSize | Size | キャンバス要素の寸法。 |
displaySize | Size | CSS でスケーリングされた表示寸法。 |
displayScale | Vector2 | baseSize と canvasBounds の比率(入力マッピングに使用)。 |
canvas | HTMLCanvasElement | ゲームのキャンバス要素。 |
canvasBounds | Rectangle | キャンバスの DOM バウンディング矩形。 |
parent | HTMLElement | 親の DOM 要素。 |
parentIsWindow | boolean | 親が document.body の場合に true。 |
resizeInterval | number | ポーリング間隔(ミリ秒)(書き込み可能)。 |
主要なメソッド
| メソッド | 戻り値 | 説明 |
|---|---|---|
resize(width, height) | this | NONE モード用: ゲーム、ベース、表示サイズを直接設定します。キャンバス要素と CSS を更新します。 |
setGameSize(width, height) | this | スケーリングモード(FIT など)用: ベースのゲームサイズを変更し、スケーリングを再適用します。 |
setParentSize(width, height) | this | 親要素の寸法を手動で設定します(parent: null の場合に便利です)。 |
setZoom(value) | this | 実行時にズーム倍率を変更します。 |
setMaxZoom() | this | 親要素に収まる最大の整数にズームを設定します。 |
setSnap(snapWidth, snapHeight) | this | スナップグリッドの値を設定またはリセットします。 |
getMaxZoom() | number | 最大ズームを計算します(適用はしません)。 |
getViewPort(camera?, out?) | Rectangle | 表示領域の矩形を取得します。オプションで特定のカメラを指定できます。 |
refresh(prevW?, prevH?) | this | スケール、境界、向きの再計算を強制します。RESIZE を発行します。 |
startFullscreen(options?) | void | フルスクリーンに入ります。pointerup から呼び出す必要があります。 |
stopFullscreen() | void | フルスクリーンを終了します。 |
toggleFullscreen(options?) | void | フルスクリーン状態を切り替えます。 |
lockOrientation(orientation) | boolean | 画面の向きのロックを試みます(モバイルのみ)。 |
transformX(pageX) | number | DOM の pageX をゲーム座標に変換します。 |
transformY(pageY) | number | DOM の pageY をゲーム座標に変換します。 |
getParentBounds() | boolean | 親要素のサイズを再計算します。変更があった場合は true を返します。 |
updateCenter() | void | センタリングのマージンを再計算して適用します。 |
updateBounds() | void | キャンバスのバウンディングクライアント矩形から canvasBounds を更新します。 |
注意点
-
親要素にはサイズが必要です。 ScaleManager は親要素の計算済み CSS サイズに依存します。スタイルが適用されていない
<div>は高さがゼロになり、センタリングとスケーリングが壊れます。明示的な CSS サイズを指定するか、expandParent: true(デフォルト)で body/親要素を 100% の高さに設定してください。 -
親要素にパディングを付けないでください。 ScaleManager は親要素のパディングを考慮しません。代わりにラッパー要素にパディングを適用するか、親要素の親要素にマージンを使用してください。
-
canvas に直接スタイルを適用しないでください。 ScaleManager は
canvas.style.width、canvas.style.height、marginLeft、marginTopを制御します。canvas への外部 CSS は競合します。 -
フルスクリーンには
pointerdownではなくpointerupが必要です。 タッチデバイスでは、ドキュメントがすでにタッチ入力を受け取っていない限り、pointerdownによるフルスクリーンリクエストはブロックされます。確実に動作させるには常にpointerupを使用してください。 -
iframe 内のフルスクリーンには
allowfullscreenが必要です。 iframe 要素にこの属性がないと、フルスクリーンリクエストはサイレントに失敗します。 -
RESIZE モードと GPU フィルレート。 RESIZE は親要素に一致する 1:1 ピクセルの canvas を作成します。高解像度ディスプレイでは非常に大きくなる可能性があります。低スペックデバイスでのパフォーマンスを監視してください。
-
resize()とsetGameSize()の違い。resize()は NONE モードでのみ使用してください(すべてを直接設定します)。FIT/ENVELOP などを使用する場合はsetGameSize()を使用してください(スケールモードの計算を保持します)。 -
iOS の高さの癖。 iOS で親要素がウィンドウの場合、ScaleManager は
GetInnerHeightを使用して、Safari の動的ツールバーがgetBoundingClientRectに影響を与える問題を回避します。 -
パーセント文字列にはサイズ指定された親要素が必要です。
width: '100%'やheight: '100%'を設定すると、parentSizeを基準に解決されます。親要素にサイズがない場合は、window.innerWidth/innerHeightにフォールバックします。 -
resizeIntervalはフォールバックポーリングです。 最新のブラウザはresizeイベントをディスパッチしますが、ScaleManager は古いブラウザのエッジケースを捕捉するために、resizeIntervalミリ秒(デフォルト 500)ごとにもポーリングします。
ソースファイルマップ
| ファイル | 目的 |
|---|---|
src/scale/ScaleManager.js | メインクラス -- すべてのスケーリング、センタリング、フルスクリーン、オリエンテーションのロジック。game.scale からアクセスします。 |
src/scale/const/SCALE_MODE_CONST.js | スケールモード定数: NONE、WIDTH_CONTROLS_HEIGHT、HEIGHT_CONTROLS_WIDTH、FIT、ENVELOP、RESIZE、EXPAND。 |
src/scale/const/CENTER_CONST.js | センターモード定数: NO_CENTER、CENTER_BOTH、CENTER_HORIZONTALLY、CENTER_VERTICALLY。 |
src/scale/const/ZOOM_CONST.js | ズーム定数: NO_ZOOM、ZOOM_2X、ZOOM_4X、MAX_ZOOM。 |
src/scale/const/ORIENTATION_CONST.js | オリエンテーション文字列定数: LANDSCAPE、LANDSCAPE_SECONDARY、PORTRAIT、PORTRAIT_SECONDARY。 |
src/scale/events/RESIZE_EVENT.js | リサイズイベントの定義。コールバックは gameSize、baseSize、displaySize、previousWidth、previousHeight を受け取ります。 |
src/scale/events/ENTER_FULLSCREEN_EVENT.js | フルスクリーンへの移行が成功したときに発行されます。 |
src/scale/events/LEAVE_FULLSCREEN_EVENT.js | フルスクリーンから退出するときに発行されます。 |
src/scale/events/FULLSCREEN_FAILED_EVENT.js | フルスクリーンリクエストが拒否されたときに発行されます。 |
src/scale/events/FULLSCREEN_UNSUPPORTED_EVENT.js | ブラウザが Fullscreen API をサポートしていないときに発行されます。 |
src/scale/events/ORIENTATION_CHANGE_EVENT.js | デバイスのオリエンテーション変更時に発行されます。コールバックはオリエンテーション文字列を受け取ります。 |
src/core/typedefs/ScaleConfig.js | scale 設定オブジェクトの JSDoc typedef。 |
src/structs/Size.js | gameSize、baseSize、displaySize で使用される Size コンポーネントクラス。 |
src/dom/GetInnerHeight.js | 正確なビューポートの高さを取得するための iOS 固有の回避策。 |
src/dom/GetScreenOrientation.js | 寸法から現在の画面オリエンテーションを判定します。 |