はじめに
今回、HTML/CSSベースのホームページにLive2Dを組み込み、公開しました。
Live2D SDK for webの初心者向け公式Youtube動画(https://www.youtube.com/watch?v=tQdkFvw7X-E )または公式テキストチュートリアルにより、ローカル環境でLive2Dをブラウザ表示できます。本記事では、その状態から既存のHTML/CSSベースのホームページにパーツとして組み込む方法をまとめます。
ここでは、Viteで完結する単体アプリを作る方法ではなく、ビルド済みLive2Dをパーツとして既存のWebサイトに組み込む方法を扱います。
作業の流れは、以下の通りです。
1. 環境構築。ローカルでLive2Dサンプルを動かす。(初心者向け公式Youtube動画で完了)
2. モデル差しかえ
3. 表示サイズ調整
4. DOM変更
5. パス設定
6. ビルド
7. ホームぺージhtml、cssに組み込み
8. サーバーへアップロード
SDKのバージョン等により一部仕様やパスが異なる場合があります。その場合は適宜読み替えてください。
開発環境
※本記事は以下の環境で動作確認しています
- Cubism 5 SDK for Web R5
- Conohaレンタルサーバー
- Html/css/javascriptのWebページ
前提条件
- Live2D SDK for Web のサンプルがローカル環境で動作しており、ブラウザ上でLive2Dモデルが表示できる状態であること
本記事では説明の分かりやすさのため、主に公式YouTube動画(https://www.youtube.com/watch?v=tQdkFvw7X-E )の手順をベースにしており、その動画内の方法で構築した環境を元として動作試験しています。
公式テキストチュートリアル(https://docs.live2d.com/cubism-sdk-tutorials/sample-build-web/ )などの内容でローカル環境を構築してLive2D描写出来た場合でも本記事は実施可能と思われます。
ただし、公式動画と公式テキストチュートリアルで一部手順などが異なる場合がありますので、適宜読み替えお願いします。
モデル差し替え
\Samples\Resourcesフォルダのデフォルトモデルと画像を削除し、自分のアップロードしたいLive2Dモデルのフォルダを配置します。
Live2D SDKの仕様の都合でLive2Dのフォルダ名とその中の.model3.jsonの名前を揃えます。
例)
フォルダ名:orichara16
.model3.jsonファイル名:orichara16.model3.json
lappdefine.tsの読み込みモデル名の変更をし、背景などの画像ファイル名部分を空に変更します。
以降、コード中の無記載はサンプルそのままのもので、行頭の+は追加した行、-は削除した行です。
// モデルの後ろにある背景の画像ファイル
- export const BackImageName = 'back_class_normal.png';
+ export const BackImageName = '';
// 歯車
- export const GearImageName = 'icon_gear.png';
+ export const GearImageName = '';
// 終了ボタン
- export const PowerImageName = 'CloseNormal.png';
+ export const PowerImageName = '';
// モデル定義---------------------------------------------
// モデルを配置したディレクトリ名の配列
// ディレクトリ名とmodel3.jsonの名前を一致させておくこと
- export const ModelDir: string[] = ['Haru', 'Hiyori', 'Mark', 'Natori', 'Rice', 'Mao', 'Wanko', 'Ren'];
+ export const ModelDir: string[] = ['orichara16'];
上記変更後、Shift+Ctrl+P ⇒ Tasks: Run Task ⇒ npm: startし、表示されたURLをブラウザ表示すると適切に置き換え後のモデルが表示されます。
エラー対応
上のように不要な画像を消すと、関係したところでエラーが出るため、無効化します。(ブラウザ上でキーボードF12を押してConsoleで確認)
- // 歯車にタップしたか
- /*if (this._gear.isHit(posX, posY)) {
- lapplive2dmanager.nextScene();
- }
- */
また、後にサーバーへアップロードしたら表示はされたものの下記エラーが出たので、下のように画像関連を30~40行ぐらいまとめてコメントアウトしました。
エラー内容:Resources/:1 GET https://xxxxxxxx.net/Resources/ 403 (Forbidden)
public initializeSprite(): void {
const width: number = this._subdelegate.getCanvas().width;
const height: number = this._subdelegate.getCanvas().height;
const textureManager = this._subdelegate.getTextureManager();
const resourcesPath = LAppDefine.ResourcesPath;
let imageName = '';
// 背景画像初期化
imageName = LAppDefine.BackImageName;
- /*
- // 非同期なのでコールバック関数を作成
- const initBackGroundTexture = (textureInfo: TextureInfo): void => {
- const x: number = width * 0.5;
- const y: number = height * 0.5;
- ...
- textureManager.createTextureFromPngFile(
- resourcesPath + imageName,
- false,
- initGearTexture
- );
-*/
// シェーダーを作成
if (this._programId == null) {
表示サイズ・位置調整
ここでは「画面上の見た目サイズ・位置調整」を行います。
lappdefine.tsファイル内部のCanvas設定(CanvasSize)は解像度(canvas.width/height)を変更するもののようで、ぼやけ具合とアスペクト比は変わりますが、見た目サイズではないようでした。そこで、表示サイズはcanvas.style.width/heightで調整しました(canvas.style.widthが表示サイズ。styleの有無で意味が違う)。
また、既存のホームページに組み込む都合で、外部からCSSで位置、サイズなどは制御したいということもありました。そのため、htmlの親のcssによって決まるようにするために下コードlappdelegate.tsのようにwidth, height共に100%に変更しました。
private initializeSubdelegates(): void {
let width: number = 100;
let height: number = 100;
...
- canvas.style.width = `${width}vw`;
- canvas.style.height = `${height}vh`;
+ canvas.style.width = `${width}%`;
+ canvas.style.height = `${height}%`;
また、Live2Dをhtmlの任意の場所に置けて、位置制御などしやすいようにするため、live2d-containerという名前のタグの場所にLive2Dを組み込むように変更しました。
private initializeSubdelegates(): void {
let width: number = 100;
let height: number = 100;
+ const container = document.getElementById('live2d-container');
if (LAppDefine.CanvasNum > 3) {
...
// キャンバスを DOM に追加
- document.body.appendChild(canvas);
+ container.appendChild(canvas);
最終的には本記事ではビルド後にホームページ側のhtmlやcssで位置・サイズ調整をしますが、ここではその前の一時的なものとしてサンプル中html内にcssのようなものと、Live2Dを組み込むタグ付きのdivを書きます。
<style>
...
- body > canvas:only-child {
+ #live2d-container {
width: 100vw;
height: 100vh;
}
</style>
...
<body>
+ <div id="live2d-container"></div>
</body>
上記の通りに修正することで、Live2Dモデルが画面いっぱいにLive2Dモデルが映ると思います。表示されたら、試しに、index.html中のcss的な描写設定部分である#live2d-container {...}の中身を試しに変えてみましょう。それ通りに表示サイズや位置が変わると思います。
パス設定と構成
- lappdefine.ts中のフォルダパス設定
- Viteの設定ファイルvite.config.mtsのbaseパス(公開時のURLのベースパス)
を自分の環境に合わせます。SDKのバージョンで何のパスが出ているか若干違うかもしれませんが、lappdefine.tsにパス設定があったら自分の設定に修正します。
2パターンでの例を示します。(SDKのバージョン:Cubism 5 SDK for Web R5の場合)
- パターン1:Live2Dを表示したいhtmlがあるフォルダ位置にビルド済みLive2Dフォルダ一式を置くパターン
- パターン2:どこからでも実行できるようにしたパターン
まずは、比較的簡単なパターン1について説明し、その後、実運用よりなパターン2をそれぞれWeb公開まで説明していきます。
個人で簡単に作りたいという場合はとりあえずやってみて、ブラウザで見てキーボードF12を押して開発者ツールを表示し、右下のコンソールでパスが間違ったらどう間違ってるか出るので、それを参考に調整する、もしくはそこにファイルを置いてしまうとしてしまったほうが簡単だと思います。
【パターン①:htmlもSDKビルド済みフォルダもすべて同じ場所に置くパターン】
パス設定(パターン①:簡易構成)
最終的な公開時に下記のようにLive2Dを組み込みたいページのhtmlファイル、ビルド済みのLive2Dを全部同じ場所に置く例です。
https://xxxxxxxxx.com/
|---既存ホームページ関係のファイル...
|---hogeフォルダ(既存のホームページのフォルダ)
|---既存ホームページ関係のファイル...
|---index.html(live2Dを表示したい既存ホームページhtml)
|---page2.html(live2Dを表示したい既存ホームページhtml)
|---assets(後述ビルド済みLive2Dフォルダ)
|---Core(後述ビルド済みLive2Dフォルダ)
|---Framework(後述ビルド済みLive2Dフォルダ)
|---Resources(後述ビルド済みLive2Dフォルダ)
この場合、vite.config.mtsと、lappdefine.tsを相対パスに下記のように書き換えます。
./Resources等は開発時とビルド後で参照先が変わりますが、最終的にHTMLと同じ階層にResources等を配置すれば動作します
- export const ResourcesPath = '../../Resources/';
+ export const ResourcesPath = './Resources/';
- export const ShaderPath = '../../Framework/Shaders/WebGL/';
+ export const ShaderPath = './Framework/Shaders/WebGL/'; //⇐SDKのバージョンによっては、一行上のShaderPathがないかも、なければ追加不要
- base: '/',
+ base: './',
productionビルド(パターン①:簡易構成)
サーバーにアップロードするための本番用ビルドをしていきます。
VS codeでShift+Ctrl+Pを押して、
Tasks: Run Task ⇒ npm: build:prod - Samples/TypeScript/Demo
を実行することで、本番環境用のビルドが完了し、ビルド済みのLive2Dフォルダ一式ができます。
サンプルデフォルトでは
Samples/TypeScript/Demo/dist
が出力フォルダになってました。Shift+Ctrl+Pを押して、
Tasks: Run Task ⇒ npm: serve - Samples/TypeScript/Demo
をすると、下記のようにリンクが出るので、リンクを押すとブラウザで映像が表示されるので動作確認します。
http://localhost:5000/
スマホで確認したい場合は、同じWiFiに繋がっている状態で、Networkとして表示されている下のようなアドレスをスマホのブラウザでURLに手打ちすると動作試験できます。
http://192.xxx.xxx.xxx:5000/
既存ホームページと結合する(パターン①:簡易構成)
<!-- Live2DCubismCore script -->
<script src = "./Core/live2dcubismcore.js"></script>
<!-- Build script -->
<script type="module" crossorigin src="/assets/index-xxxxxxx.js"></script>
<div id="live2d-container"></div>
ビルドで出力されたdistフォルダ中のindex.htmlを参考に、既存ホームページのhtmlへ追加し、既存ホームページのcssにどう表示するかを追加していきます。
まずは、<head>にLive2DのSDKと起点となるjavascriptの実行分を下記のように追加します。また、ビルドするたびにindex-xxxxxxx.jsのファイル名が変わるので、ビルドして名前が変わったら変更して合わせる必要があります。
<head>
...
+ <!-- Live2DCubismCore script -->
+ <script src = "./Core/live2dcubismcore.js"></script>
+ <!-- Build script -->
+ <script type="module" crossorigin src="./assets/index-xxxxxxx.js"></script>
そして、Live2Dモデルを挿入したい場所に下記のように追加します。
+ <div id="live2d-container"></div>
既存ホームページのcssにlive2d-containerタグの表示設定を追加します。下コードは右下に前面配置で背景のホームページをクリックできるようにする例です。内容はご自由にしてください。
+ #live2d-container {
+ position: fixed;
+ width:100vw;
+ height: 50vh;
+ bottom: -10px;
+ right: -30vw;
+ z-index: 1000;
+ pointer-events: none;
+ }
レンタルサーバーにデプロイする(パターン①:簡易構成)
公開したLive2Dモデルはブラウザに配信されるため、第三者によるデータの取得を完全に防ぐことは困難です。公開するLive2Dモデルの権利に注意しましょう。
また、Live2DをWeb公開前に、Live2D SDKのライセンスを事前に確認してください。
さらに、cmo3ファイル(Live2Dモデリング編集ファイル)とPSDファイル(パーツ分けイラスト)がLive2Dモデルファイル内に入っている場合、編集用データは公開に不要なため、アップロードしないことをおすすめします。
ビルド済みのLive2Dフォルダであるdistフォルダの中のindex.html以外のフォルダと、ホームページのファイルを下記のように置きます。
誤ってホームページのindex.htmlをdistフォルダ中のindex.htmlで上書きして消さないよう注意してください。
https://xxxxxxxxx.com/
|---既存ホームページ関係のファイル...
|---hogeフォルダ(既存のホームページのフォルダ)
|---既存ホームページ関係のファイル...
|---index.html(live2Dを表示したいSDK用に追記した既存ホームページhtml)
|---page2.html(live2Dを表示したいSDK用に追記した既存ホームページhtml)
|---assets(ビルド済みLive2Dフォルダ)
|---Core(ビルド済みLive2Dフォルダ)
|---Framework(ビルド済みLive2Dフォルダ)
|---Resources(ビルド済みLive2Dフォルダ)
私の環境ではConohaレンタルサーバーにConoha標準の用意されているファイルマネージャーでビルド済みLive2Dフォルダをアップロードしたところエラーになって表示されませんでした。そのため、FileZilaというフリーソフトを使ってアップロードしたところ正常に動作しました。たぶん、FileZilaではバイナリ形式でデータを送っていたためファイルが壊れずに正常に動いたのかと思ってます。
これで、ホームページへのLive2Dモデル組み込み完了です!
実際に組み込んだホームページ例⇒ https://fugi-himitsukichi.net/
【パターン②:htmlの配置場所は自由、ビルド済みSDKは事前指定の場所に置くパターン】
パス設定(パターン②:配置自由度高めの構成)
パターン②はより自由度の高いファイル構成に対応します。最終的な公開時に下記のようにhtmlはどこに置いてもよく、ビルド済みのLive2Dはvite.config.mtsのbaseに書いた場所に全部置く場合の例です。下記ではドメイン直下にlive2dという名前のフォルダを作ってビルド済みLive2Dを入れてます。以降パターン①の知識はあるの前提で話を進めます。
https://xxxxxxxxx.com/
|---index.html(live2Dを表示したいページ。どこにおいてもいい)
|---pages(フォルダ)
|---page2
|--- page2.html(live2Dを表示したいページ。どこにおいてもいい)
|---live2d(フォルダ)
|---assets(ビルド済みLive2Dフォルダ)
|---Core(ビルド済みLive2Dフォルダ)
|---Framework(ビルド済みLive2Dフォルダ)
|---Resources(ビルド済みLive2Dフォルダ)
|---index.html(ビルド済みLive2Dhtml。あっても悪さしないのでデバッグ用においておく)
// 相対パス
- export const ResourcesPath = '../../Resources/';
+ const baseResourcesPath = new URL('../Resources/', import.meta.url).href;
+ export const ResourcesPath =baseResourcesPath.endsWith('/') ? baseResourcesPath : baseResourcesPath + '/';
// シェーダー相対パス
- export const ShaderPath = '../../Framework/Shaders/WebGL/';
+ const baseShaderPath = new URL('../Framework/Shaders/WebGL/', import.meta.url).href;
+ export const ShaderPath =baseShaderPath.endsWith('/') ? baseShaderPath : baseShaderPath + '/';
Live2DをSDKで描写する際に、Live2D SDKはビルド済javascriptファイルを起点として実行することでLive2Dを表示します。違うフォルダにあるhtmlファイルからそのLive2Dのjavascrptを実行すると、./の基準位置がhtmlファイルがあるフォルダ位置になってしまうため、javascript内の相対パスが狂ってしまいエラーになります。
上のコードでは、どこにあるhtmlからでもLive2Dを使えるようにするため、javascript内のパスを./~ではなくjavascriptのフォルダ位置を基準にしています。import.meta.urlでLive2Dのjavascriptファイル位置を取得し、そこを基準にパス設定をするようにしています。
- base: '/',
+ base: '/live2d/',
上記のようvite.config.mtsについても、公開時のビルド済みLive2Dフォルダを置く場所であるbaseを、サーバーで置く場所にに書き換えます。
npm:startしている状態でvite.config.mtsを書き変えても画面は更新されません。
Ctrl+Cで一度止めてから、再度Tasks: Run Task ⇒ npm:startしましょう。
上を変えたことで、ブラウザを開くときのURLが以下のように"/live2d"分だけ変わりますので、新しいほうを開いてデバッグします。
http://localhost:5000
↓
http://localhost:5000/live2d/
既存ホームページと結合する(②:配置自由度高めの構成)
ビルドで出力されたdistフォルダ中のindex.htmlを参考に、既存ホームページのhtmlに追加し、既存ホームページのcssにどう表示するかを追加していきます。
まずは、<head>にLive2DのSDKと起点となるjavascriptの実行分を下記のように追加します。パスは実際のサーバー環境に合わせます。パターン①と比べて/live2dが増えています。また、今回はどこから見ても同じになるように相対パスではなく絶対パスにするため、'.'を消しています。
<head>
...
+ <!-- Live2DCubismCore script -->
+ <script src = "/live2d/Core/live2dcubismcore.js"></script>
+ <!-- Build script -->
+ <script type="module" crossorigin src="/live2d/assets/index-xxxxxxx.js"></script>
その他はこの工程においてはパターン①と全く同じです。Live2Dモデルを挿入したい場所へ挿入用のタグ追加、cssを変更します。
レンタルサーバーにデプロイする(パターン②:配置自由度高めの構成)
指定した場所(今回だとlive2dフォルダを作ってその中)に、ビルド済みLive2Dフォルダであるdistフォルダの中のフォルダ・ファイル全てを入れます。また、ホームページのファイルは既存のファイル構成そのままで大丈夫です。
https://xxxxxxxxx.com/
|---既存のホームページの構成そのまま
|---...
|---live2d(フォルダ)
|---assets(ビルド済みLive2Dフォルダ)
|---Core(ビルド済みLive2Dフォルダ)
|---Framework(ビルド済みLive2Dフォルダ)
|---Resources(ビルド済みLive2Dフォルダ)
|---index.html(ビルド済みLive2Dhtml。あっても悪さしないのでデバッグ用においておく)
これで、自由なファイル構成でのホームページへのLive2Dモデル組み込み完了です!
補足(いくつか実用的なSDK変更)
背景透過
下記変更で背景透過します。これでキャラクターの背景のホームページが適切に見えます。
- gl.clearColor(0.0, 0.0, 0.0, 1.0);
+ gl.clearColor(0.0, 0.0, 0.0, 0.0);
マウス位置取得に対するスクロールの分慮
Webページをスクロールしてもキャラクターが常に特定の位置にいるみたいな固定されている場合、サンプルのままだとマウスやクリック位置の座標がスクロール分だけ動きがずれます。その場合、スクロール分だけ補正すると正常に動きます。
+ const localX: number = pageX - rect.left - scrollX;
+ const localY: number = pageY - rect.top - scrollY;
複数、上と同じコードはありますが変更場所は例えば"クリックが終了した時"や"マウスが動いた時"など下記みたいにコード中に書かれてるので該当部分を変更します。
/**
* マウスポインタが動いたら呼ばれる。
*/
public onPointMoved(pageX: number, pageY: number): void {
クリックしなくてもマウスで動くようにする
サンプルデフォルトだとPCでマウスをドラッグしないとキャラクターが動きません。下記のように、フラグをコメントアウトすると、ブラウザがアクティブの時はクリックしなくてもマウス位置で動くようになります。
public onPointMoved(pageX: number, pageY: number): void {
- //if (!this._captured) { return; }
おわりに
以上で、ホームページにLive2Dモデルを表示することができました。SDKのバージョンによって違いがあるかもしれませんが、参考になる部分があったら嬉しいです。
余談(なぜ本記事の方法でLive2Dを組み込んだのか)
Live2Dを組み込むうえで以下の2つの方法も検討しましたが、結局、本記事の方法を選択しました。
- 方法i. サンプルコードにがっつりホームページを組み込んで、Viteですべて完結する。
- 方法ii. iframeを使って、別ページとしてLive2D部分をページに組み込む。
まず、方法iについては統一性があって良いですし、特定1ページをアプリ的に作りたいならそうすると思いました。
しかし、今回はあくまで既存のホームページありきで、Live2Dを面白みとして追加したいというのが目的でした。今後、ホームページ更新のたびにTypeScriptやビルド設定などSDK関係を触るのが面倒かもと思いました。また、私はLive2D以外にもいろいろ試したいので、可能な限りホームページのベースはシンプルにしたいと思い、今回はこの方法は避けました。
方法iiについては、今回やったことと同様にパーツとして使える上に、Live2D側をビルドするたびにhtmlのindex-xxxxxxx.jsの名前を変えなくてよいし、どこに置いても参照が簡単で良いと一見思いました。しかし、試しましたが、
・Live2Dの描写領域でしかマウス位置やクリックを拾わない
・前面に出して背景透過して後ろをクリックでき、且つ、マウス位置を拾ったり、キャラタッチが反応したりというのを同時達成が標準ではできない。
という問題がありました。いろいろ頑張ればできる要素もあるみたいですが、少なくとも素直には出来ないので避けました。
結果として、本記事でご紹介した方法にてLive2Dを組み込みました。
デモ(Live2Dを組み込んだ自ホームページ)
