NarraLeaf

カメラ

ステージ全体をパン・ズーム・カラーグレーディングする `Camera` 要素。シャッター、ビネット、レンズ効果も含む

このクラスは Displayable を継承しています

カメラはステージ全体を一つの単位として変換します。すべての Scene と、その背景・スプライト、再生中の Video が一緒に動きます。ダイアログボックス、メニュー、NVL レイヤーは固定されたままです。

すべての Story はカメラをちょうど一つ持ち、story.camera としてアクセスできます。カメラのアクションは、他の要素のアクションと同じように記述します。

import { Story, Scene, Character } from "narraleaf-react";

const story = new Story("entry");
const scene = new Scene("scene 1");
const aria = new Character("Aria");

scene.action([
    story.camera.zoom(2, 800, "easeInOut"),   // ステージ全体をズームイン
    story.camera.pan({ xalign: 0.3 }, 800),   // 視界をスライドさせる
    story.camera.rotate(3, 400),              // 傾ける
    story.camera.darken(0.6, 500),            // ステージを暗くする
    aria.say`It's getting dark...`,
    story.camera.resetCamera(600),            // ニュートラルなポーズに戻す
]);

カメラは画像やレイヤーと同じ Transform パイプラインを再利用しているため、 Displayable が持つチェーン可能な変換メソッドをすべて継承しています: poszoomscalerotateopacitytransformfiltereffect など。これらはすべてステージ全体に適用されます。

カメラへのアクセス

story.camera は常に存在する単一のカメラです。ストーリーごとにちょうど一つ存在し、そのポーズはシーンが切り替わっても保持され、他の要素と同様にセーブ・ロードの対象にもなります。

scene.action([
    story.camera.zoom(1.5, 600),
    story.camera.darken(0.4, 400),
]);

公開メソッド

pan

指定した位置がビューの中心に来るようにカメラをパンします。これは継承した pos メソッドに、カメラ向けの名前を付けたエイリアスです。

story.camera.pan({ xalign: 0.3 }, 800, "easeInOut");

darken

ステージ全体を暗くします。darkness0(通常)から 1(真っ黒)までの値です。内部的にはカメラの CSS filterbrightness(1 - darkness) に設定しており、Image.darken と同じ仕組みです。

story.camera.darken(0.6, 500, "easeInOut");

darken は単一の CSS filter チャンネルを共有しているため、他のフィルターを上書きし、また上書きされます。 blur など他のフィルターと組み合わせるには、camera.filter("blur(4px) brightness(0.4)") のように完全な文字列を自分で書いてください。

shutter

0.31.0 から利用可能

シャッターを閉じたり開いたりします。画面の中央で合わさる2枚の羽根です。

1 が完全に閉じた状態、0 が完全に開いた状態で、その間の値は部分的な遮蔽になります。そのため小さな値を維持し続けるとまばたきではなくレターボックスになり、0.12 程度が映画的なマットに相当します。まばたきは、この値を 1 まで動かしてから戻す操作です。まばたきのタイミングはストーリー側が決めるものなので、エンジンは名前付きの定型処理ではなくこのチャンネル自体を提供しています。

  • shutter: number - 0(開)から 1(閉)までの遮蔽度。範囲外の値はクランプされます
  • duration?: number
  • easing?: EasingDefinition
scene.action([
    story.camera.shutter(1, 180, "easeInOut"),
    story.camera.shutter(0, 220, "easeInOut"),
]);

vignette

0.31.0 から利用可能

画面の四隅を暗くします。

画像全体にかかるフィルターである darken とは異なり、これはビューの上に重ねられる板です。カメラと一緒には動かないため、その下のステージがズームやパン、回転をしていてもビネット自体は静止したままです。減衰の度合いは lens で調整します。

  • vignette: number - 0(なし)から 1 までの強度。範囲外の値はクランプされます
  • duration?: number
  • easing?: EasingDefinition
scene.action([
    story.camera.vignette(0.72, 300, "easeInOut"),
    narrator.say`Everything narrowed to the middle of the room.`,
    story.camera.vignette(0, 300, "easeInOut"),
]);

lens

0.31.0 から利用可能

レンズの各チャンネルを一度に設定します — 2つの強度と、それらを描画する際の色や減衰の形状です。

形状に関するフィールドは、対応する強度が次に 0 を超えたタイミングで反映されます。そのため通常は、効果をフェードインさせる前にカット的に設定しておきます。

type CameraLensProps = {
    shutter?: number;        // 0 で開、1 で閉。デフォルトは 0
    shutterColor?: string;   // デフォルトは "#000"
    vignette?: number;       // 0 でなし、1 で端が完全に不透明。デフォルトは 0
    vignetteColor?: string;  // デフォルトは "#000"
    vignetteInner?: string;  // ビネットが始まる半径。デフォルトは "44%"
    vignetteOuter?: string;  // 最大強度に達する半径。デフォルトは "78%"
};
  • lens: CameraLensProps
  • options?: VisualEffectOptions
scene.action([
    story.camera.lens({vignetteColor: "#1a0b2e", vignetteInner: "20%", vignetteOuter: "95%"}),
    story.camera.vignette(0.9, 400),
]);

resetCamera

カメラをニュートラルなポーズに戻します: 中央に配置、ズーム 1、回転なし、完全不透明、フィルターなし(これにより darken もクリアされます)。

story.camera.resetCamera(600, "easeInOut");

フィルターは最初のフレームでクリアされ、ポーズは指定した時間をかけてイージングします。

グレードを置き換える場合は時間を指定しないでください。あるフィルターチェーンから別のチェーンへイージングすると、ステージはその間の色を経由することになります。

0.26.0 でリネームされました。以前は camera.reset という名前でした。 すべての要素は内部的な reset() を 持っています — これは新しいゲームの開始時やセーブのロード時にエンジンがキャスト全体に対して実行するライフサイクルフックです。 カメラはこの名前を、この作成用ヘルパーメソッドに使ってしまっていたため、newGame() はカメラのポーズを一度も復元できず、 パンやズームを行ったストーリーは、その構図を次のプレイに持ち越してしまっていました。

スクリプト内の camera.reset(...) はすべてリネームしてください。カメラで reset() を呼び出すと、今はライフサイクルフックの 方に届きます。設定されたポーズに即座に復元し、アニメーションは行わず、チェーン可能なアクションではなくカメラ自体を返します。

継承した変換メソッド

カメラは Displayable であるため、その変換機能のすべてがステージ全体を動かします:

  • zoom(factor, duration?, easing?) — 均等にズームイン・ズームアウトします。
  • scale(scaleX, scaleY, duration?, easing?) — 不均等なスケーリングを行います。
  • rotate(deg, duration?, easing?) — ビューを回転させます。
  • pos(position, duration?, easing?) — パンします(pan を参照)。
  • opacity(value, duration?, easing?) — ステージ全体をフェードさせます。
  • filter(css, options?) / effect(...) — ステージをカラーグレーディングします(例: "contrast(1.2) saturate(1.3)")。
  • transform(new Transform(...)) — 複数ステップからなる Transform シーケンス全体を実行します。

初期ポーズの設定

ストーリーごとにカメラはちょうど一つです。開始時のポーズを設定したい場合にのみ、自分でカメラを渡します:

import { Story, Camera } from "narraleaf-react";

const story = new Story("entry", {
    camera: new Camera({ zoom: 1.2 }),
});

カメラが動かすのは視覚的なステージのみです。ダイアログボックス、メニュー、NVL レイヤーはその外側でレンダリングされ、 意図的に影響を受けません。そのため、カメラが動いている間もテキストは読みやすいままです。

このページの目次