スマートフォンのカメラ機能をより便利に使いこなそうと考えた際に思いつくのが、アプリの中に映像を埋め込む方法ではないでしょうか。その映像を取得できれば、より面白いアプリが作れそうです。

今回はそうしたアプリを作る際に必須となりそうなCanvasCameraPluginの使い方を解説します。

下の動画は、端末のカメラから取得した映像をアプリ内で表示しているところです。

プロジェクトのソースコードは、GitHubに配置しています。
https://github.com/monaca-samples/CanvasCameraPluginApp

CanvasCameraPluginのインストール

CanvasCameraPluginはMonaca IDEのCordovaプラグインの追加と削除よりインストールしてください。

https://github.com/VirtuoWorks/CanvasCameraPlugin.git

事前設定 (iOSのみ)

CanvasCameraPluginではカメラを使いますので、iOSの場合にはconfig.xmlを編集する必要があります。

<edit-config file="*-Info.plist" mode="merge" target="NSCameraUsageDescription">
        <string>カメラの映像を利用します</string>
</edit-config>

HTMLについて

カメラの映像を投影するcanvasタグを用意します。

これは複数指定できます。今回はフルサイズ表示する #fullsize とサムネイル表示用の #thumbnail を用意しています。

<canvas class="raster" id="fullsize"></canvas>
<canvas class="raster" id="thumbnail"></canvas>

初期化

アプリが立ち上がったタイミングで初期化を行います。ここでHTMLのcanvasを指定します。

window.plugin.CanvasCamera.initialize({
    fullsize: document.querySelector("#fullsize"),
    thumbnail: document.querySelector("#thumbnail"),
});

カメラ映像の表示

映像を映し出す際には、次のように処理を実行します。

successCallback には随時データが流れてきます。一度だけではない点に注意してください。

window.plugin.CanvasCamera.start(options, errorCallback, successCallback);

オプションのパラメータ

options で映像の取得方法を指定できます。

例として、下記にのようになります。大事なポイントとして use: "data" があります。
file:// を指定した場合、パーミッション関係するエラーが発生します。

const options = {
    // canvasタグの大きさを指定
    canvas: {
        width: 320,
        height: 240,
    },

    // キャプチャする大きさを指定
    // canvasと同じ大きさにしておくのが良さそうです
    capture: {
        width: 320,
        height: 240,
    },

    // dataやfileなどが指定できます
    use: "data",
    // FPS
    fps: 30,
    // フラッシュを使う場合は true
    flashMode: false, // または true
    // サムネイルがある場合は true
    hasThumbnail: true,
    // サムネイルの大きさを指定
    thumbnailRatio: 1 / 6,
    // 利用するカメラの場所
    cameraFacing: 'back', // または front
};

受信するデータ

successCallbackに送られてくるデータは、次のようになります。

FPSに合わせて随時データが送られてきます。

{
    "preview": {
        "started": true
    },
    "message": "OK",
    "options": {
        "height": 288,
        "canvas": {
            "width": 320,
            "height": 240
        },
        "cameraFacing": "back",
        "thumbnailRatio": 0.16666666666666666,
        "width": 352,
        "fps": 30,
        "flashMode": false,
        "hasThumbnail": true,
        "capture": {
            "width": 352,
            "height": 288
        }
    },
    "output": {
        "images": {
            "thumbnail": {
                "rotation": 0,
                "data": "data:image/jpeg;base64,/9j/4AAQS.../9k=",
                "timestamp": 1658160100040.1157,
                "orientation": "landscape"
            },
            "fullsize": {
                "rotation": 0,
                "data": "data:image/jpeg;base64,/9j/...f/9k=",
                "timestamp": 1658160100040.105,
                "orientation": "landscape"
            }
        }
    }
}

ここまでの説明で、カメラ映像をアプリ内に投影ができます。

この後はプラグインにあるメソッドの使い方を紹介します。

フロントカメラを利用する

カメラを変更する場合には cameraPosition メソッドを使います。

window.plugin.CanvasCamera.cameraPosition(
    'front', // または back
    errorCallback,
    successCallback
);

停止

停止する場合は stop を使います。なおcanvasには最後のフレームの映像が残ります。

window.plugin.CanvasCamera.stop(errorCallback, successCallback);

カメラフラッシュON/OFF

フラッシュを点ける、または停止する際には flashMode メソッドを使います。

window.plugin.CanvasCamera.flashMode(
    true, // または false
    errorCallback,
    successCallback,
);

反転

反転させるフリップも用意されています。

いままでの操作より処理は複雑となっています。

// フリップ状態を管理する変数
const flip = {};

// フリップ済みかどうか
if (flip.flipped) {
    // フリップしている場合には元に戻す
    flip.scaleH = 1;
    flip.scaleV = 1;
    flip.flipped = false;
} else {
    // フリップ(反転)指定
    flip.scaleH = -1;
    flip.scaleV = -1;
    flip.flipped = true;
}

// レンダリング前に実行されるイベント
window.plugin.CanvasCamera.beforeFrameRendering(function (event, frame) {
    this.context.save();
    frame.dWidth = frame.dWidth * flip.scaleH;
    frame.dHeight = frame.dHeight * flip.scaleV;
    this.context.scale(flip.scaleH, flip.scaleV);
});

// レンダリング後に実行されるイベント
window.plugin.CanvasCamera.afterFrameRendering(function (event, frame) {
    this.context.restore();
});

getUserMediaとの違いについて

もしあなたがHTML APIに詳しければ、カメラの映像を扱うのにgetUserMediaを使う方法が思いつくかも知れません。このgetUserMediaはカメラの映像を取得し、videoタグに投影したり、画像として取得できます。

しかし、iOS(iPhone)のwkWebViewではgetUserMediaが取得できるのは画面を最大化した時に限定されます。アプリの内部に動画を埋め込むことはできないので注意してください。

まとめ

カメラの映像を使ったチャットや、映像の上にオブジェクトを載せるなどカメラとスマホアプリの相性はとても良いです。現状のgetUserMediaでは難しい機能もCanvasCameraPluginを使えば簡単に実現できますので、ぜひ試してください。