Live2DをNuxt.jsに組み込んでみる


# Live2Dとは？
一言で表すとVtuberのアレです。
通常アニメーション作成には大量のイラストが必要になりますが、Live2Dでは1枚のイラストさえあれば下記のようなアニメーションを作成できます。
※ ↓GIFです。
![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587410/025c7e11-9a06-b9f8-36dc-bbb9dbe0f161.gif)

# 作りたいもの
Live2DはTypeScriptのSDKが公開されているので、今回は下記の様にNuxt.jsに組み込んでみたいと思います。
※モデルは表示されますが警告や幾つかスマートでないやり方です。調査が進んだら修正します。。。
※ ↓GIFです。
![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587410/70879cba-3940-df4e-3cf6-29f331ddc08f.gif)

# 1. SDKをダウンロード

https://www.live2d.com/download/cubism-sdk/download-web/

「Cubism SDK for Web」からダウンロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587410/55a1ff15-7e33-d3b7-6018-6ef9df0c1f2b.png)

# 2. サンプルを起動してみる
Gitに手順はありますが、画像付きで一応載せます。

https://github.com/Live2D/CubismWebSamples

## 2-0. 環境情報
| ツール | バージョン |
|:-:|:-:|
| Node  | v14.17.3  |
| npm  | 6.14.13  |

## 2-1. ダウンロードしたSDKをオープン
ダウンロードしたSDKを解凍してVScodeで開きます。

    CubismSdkForWeb-4-r.3/　(記事内ではプロジェクトルートと表現します)
      ├ .vscode/          # Visual Studio Code 用プロジェクト設定ディレクトリ
      ├ Core/             # Live2D Cubism Core が含まれるディレクトリ
      ├ Framework/        # レンダリングやアニメーション機能などのソースコードが含まれるディレクトリ
      ├ Samples/
      |  ├ Resources      # モデルのファイルや画像などのリソースが含まれるディレクトリ
      |  └ TypeScript     # TypeScript のサンプルプロジェクトが含まれるディレクトリ
      ├ CHANGELOG.md
      ├ cubism-info.yml
      ├ LICENSE.md
      ├ NOTICE.md
      └ README.md

## 2-2. npm installを実行
コマンドパレットを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587410/1237f4c9-3e02-e11f-54bd-27386a04ba04.png)

下記を入力して実行します。

    >Tasks: Run Task

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587410/1fa411af-23cc-335e-798c-a456025450e2.png)

下記を入力して実行します。

    npm: install - Samples/TypeScript/Demo

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587410/5d96c853-6d98-bbf6-c1b4-9f589f593e4c.png)

## 2-3. npm buildを実行
2-2の手順でnpmタスク実行画面まで進めます。
下記を入力して実行します。

    npm: build - Samples/TypeScript/Demo

ビルドが完了すると下記パスに `bundle.js` が生成されます。

    CubismSdkForWeb-4-r.3/
     └ Samples/
        └ TypeScript/
           └ Demo/
              └ dist/
                 └ bundle.js

## 2-4. SDKのデモを起動
2-2の手順でnpmタスク実行画面まで進めます。
下記を入力して実行します。

    npm: serve - Samples/TypeScript/Demo

サーバが起動したらブラウザで `http://localhost:5000` にアクセスします。
下記の画面が表示されるので「Samples/」→「TypeScript/」→「Demo/」と選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587410/65527af7-6c76-1a1c-10c3-fbb075af7302.png)

キャラクターが表示されれば成功です。(歯車マークでモデルが切り替わります)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587410/f1762713-1e54-03b4-a81c-daa22a3ea7a1.png)

# 3. モデルを追加してみる (任意)
## 3-1. モデルをダウンロード
配布しているサイトは沢山あります。(今回はBOOTHというサイトで0円のモデルを使用)

https://booth.pm/ja/items/2685284

ダウンロードしたZIPを解凍すると下記構造になっています。

    LiveroiD_A_1.1
     └ Live2DModels
        ├ LiveroiD_A-Y01 ※このフォルダ毎移動する
        └ LiveroiD_A-Y02 ※このフォルダ毎移動する
           └ LiveroiD_A-Y02.model3.json ※このファイルが必須

## 3-2. モデルをサンプルに追加
3-1でダウンロードしたフォルダを下記の階層になるように格納します。

    CubismSdkForWeb-4-r.3/
     └ Samples/
        └ Resources/
           ├ LiveroiD_A-Y01
           └ LiveroiD_A-Y02 ※1
              └ LiveroiD_A-Y02.model3.json ※1

`CubismSdkForWeb-4-r.3/Samples/TypeScript/Demo/src/lappdefine.ts`に下記定義を追記します。

```typescript:lappdefine.ts
// モデル定義---------------------------------------------
// モデルを配置したディレクトリ名の配列
// ディレクトリ名とmodel3.jsonの名前を一致させておくこと
export const ModelDir: string[] = ['LiveroiD_A-Y02'];※1 LiveroiD_A-Y02に書き換え
```
※1 モデルのディレクトリ名・モデルの～.model3.jsonの名前が一致している必要があります。
　　また一致している名称をlappdefine.tsのModelDirの定義に追記します。

## 3-3. 追加したモデルを確認
2-3の手順でbuild実行後に2-4の手順でSDKデモを立ち上げます。
追加したキャラクターが表示されれば成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587410/4f63283d-6ef2-538d-8da4-ff4f34cc80d1.png)

# 4. Live2DのSDKを改造する
## 4-1. 外部呼出し用の関数を追加
`CubismSdkForWeb-4-r.3/Samples/TypeScript/Demo/src/main.ts`に下記定義を追記します。

```typescript:main.ts
/**
 * Process when changing screen size.
 */
window.onresize = () => {
  if (LAppDefine.CanvasSize === 'auto') {
    LAppDelegate.getInstance().onResize();
  }
};

// ========= 以下を追記 =========

export function dummy() {
  // Do Nothing
}
```
※良いやり方では無いので他の方法模索中です。

## 4-2. リソース関係のパスを修正
`CubismSdkForWeb-4-r.3/Samples/TypeScript/Demo/src/lappdefine.ts`に下記定義を追記します。

```typescript:lappdefine.ts
// 相対パス
export const ResourcesPath = './Resources/'; // 読み込みパスを同一階層に書き換え

// モデルの後ろにある背景の画像ファイル
export const BackImageName = ''; // 空白に書き換え

// 歯車
export const GearImageName = ''; // 空白に書き換え

// 終了ボタン
export const PowerImageName = 'CloseNormal.png';
```

## 4-3. glコンテキストの背景を透明化
`CubismSdkForWeb-4-r.3/Samples/TypeScript/Demo/src/lappdelegate.ts`に下記定義を追記します。

```typescript:lappdelegate.ts
/**
 * 実行処理。
 */
public run(): void {
  // メインループ
  const loop = (): void => {
    // インスタンスの有無の確認
    if (s_instance == null) {
      return;
    }

    // 時間更新
    LAppPal.updateTime();

    // 画面の初期化
    gl.clearColor(0.0, 0.0, 0.0, 0.0); // 第四引数を0.0に変更
```

## 4-4. ビルド実行
2-3の手順でbuildを実行します。
生成された`bundle.js`は後で使います。

# 5. Nuxt.jsのプロジェクトを立ち上げ
## 5-1. Nuxt.jsプロジェクトの立ち上げ
次にproject直下でNuxt.jsプロジェクト作成コマンドを実行。

    $ npx create-nuxt-app nuxt_live2d_sample

プロジェクト名は変えたいならココで入力(今回は空白)

    ? Project name: (nuxt_live2d_sample)

言語を聞かれるのでTypeScriptを選択。

    ? Programming language: 
      JavaScript
    > TypeScript

パッケージマネージャ聞かれるのでYarnを選択。

    ? Package manager: (Use arrow keys)
    > Yarn
      Npm

UIフレームワークを聞かれるので取り合えずBootstrap Vueを導入。

    ? UI framework:  
      None
      Ant Design Vue 
      BalmUI
    > Bootstrap Vue

利用するモジュールを選択。

    ? Nuxt.js modules:
    >(*) Axios - Promise based HTTP client

Lintを選択。

    ? Linting tools: 
    >(*) ESLint
     ( ) Prettier
     ( ) Lint staged files
     (*) StyleLint        
     ( ) Commitlint

テストツール選択。

    ? Testing framework: (Use arrow keys)
    > None

レンダリングはSPAを選択。

    ? Rendering mode:       
      Universal (SSR / SSG) 
    > Single Page App

動作環境を選択。

    ? Deployment target:
    > Server (Node.js hosting)
      Static (Static/Jamstack hosting)

デベロッパーツールは特に指定なし。

    ? Development tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
    >( ) jsconfig.json (Recommended for VS Code if you're not using typescript)
     ( ) Semantic Pull Requests
     ( ) Dependabot (For auto-updating dependencies, GitHub only)

継続的インテグレーションは特になし！

    ? Continuous integration: (Use arrow keys)
    > None
      GitHub Actions (GitHub only)
      Travis CI
      CircleCI

バージョン管理はもちろんGitを選択。

    ? Version control system: (Use arrow keys)
    > Git

## 5-2. Nuxt.jsの起動確認
ファイルが生成されたら起動してみる。

    $ cd nuxt_live2d_sample
    $ yarn dev

立ち上がったらブラウザで「`http://localhost:3000/`」にアクセスして下記画面が出れば成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587410/ad282cf1-f3e8-a571-b783-79c171bcdcfd.png)

# 6. Nuxt.jsにLive2Dを組み込む
## 6-1. Live2DのjsとリソースをNuxt.jsに格納

    nuxt_live2d_sample/
     └ static/
        ├ Resources/          ※1
        ├ bundle.js           ※2
        └ live2dcubismcore.js ※3

※1. `CubismSdkForWeb-4-r.3\Samples\TypeScript\Demo\Resources`からコピー。
※2. `CubismSdkForWeb-4-r.3\Samples\TypeScript\Demo\dist\bundle.js`からコピー。
※3. `CubismSdkForWeb-4-r.3\Core\live2dcubismcore.js`からコピー。

## 6-2. nuxt.config.jsを編集

```typescript:nuxt.config.js
export default {
  // Disable server-side rendering: https://go.nuxtjs.dev/ssr-mode
  ssr: false,

  // Global page headers: https://go.nuxtjs.dev/config-head
  head: {
    title: 'nuxt_live2d_sample',
    htmlAttrs: {
      lang: 'en'
    },
    script: [
      {
        src: 'live2dcubismcore.js' // 追加
      }
    ],
```

## 6-3. Live2d.vueを追加

`nuxt_live2d_sample\components`に以下のファイルを追加します。

```vuejs:Live2d.vue
<template>
  <div>
  </div>
</template>

<script lang="ts">
import { dummy } from '../static/bundle'

export default {
  asyncData () {
    dummy()
  }
}
</script>

<style>
canvas {
  position: absolute;
  top: 0;
  left: 0;
}
</style>
```

## 6-4. index.vueを編集

`nuxt_live2d_sample\pages\index.vue`を以下の通り書き換えます。

```vuejs:index.vue
<template>
  <div>
    <Tutorial />
    <Live2d /> // 追加
  </div>
</template>

<script lang="ts">
import Vue from 'vue'

export default Vue.extend({})
</script>

<style>
body {
  position: relative; // 追加
}
</style>
```

## 6-5. Nuxt.js + Live2Dの起動確認

    $ cd nuxt_live2d_sample
    $ yarn dev

立ち上がったらブラウザで「`http://localhost:3000/`」にアクセスしてキャラクターが表示されれば成功です。
※ ↓GIFです。
![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587410/70879cba-3940-df4e-3cf6-29f331ddc08f.gif)