素のJavaScriptだけでLive2Dを使う ～Node.js無し

Node.js(React,Vue,TypeScript)を使いません。
HTMLファイルをLiveServerやxamppのローカルサーバーで起動し、Live2Dを扱えるものです。
もちろんNode.js類とも組み合わせることができます。

ローカルサーバー(何らかのサーバー)で起動して下さい。
サーバー使わないとCDN関係クロスオリジンポリシーで弾かれます。

Replit サンプルページ 
-------
デモ
https://live2dexample--supica8219.repl.co/
コード
https://replit.com/@supica8219/Live2Dexample#index.html

github
---------
https://github.com/shizusouth/Live2DSample

上記Replitのリンクでコードと動作が見られます。

以下のようなLive2DデータHiyoriを使いました。
下記URLから桃山ひよりプロ版をダウンロードします。runtimeフォルダの名前をrumtime->Hiyoriにしています。
https://www.live2d.com/download/sample-data/

![Screenshot 2022-09-22 004836.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1364047/b54a112a-6974-a0fa-4567-ff1e8949aa22.png)




# index.html　
```html:index.html
<!DOCTYPE html>
<html>
<head>
  <title>Live2Dサンプル</title>
    <!-- Live2D -->
  <script src="./live2dcubismcore.js"></script>
  <script src="//cdn.jsdelivr.net/gh/dylanNew/live2d/webgl/Live2D/lib/live2d.min.js"></script>
  <!-- PixiJS -->
  <script src="//cdnjs.cloudflare.com/ajax/libs/pixi.js/5.1.3/pixi.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/pixi-live2d-display/dist/index.min.js"></script>
  <!-- Kalidokit -->
  <script src="//cdn.jsdelivr.net/npm/kalidokit@1.1/dist/kalidokit.umd.js"></script>
</head>
<body>
<button onclick="Motion(1);">モーション1</button>
<button onclick="Motion(2);">モーション2</button>
<button onclick="Motion(3);">モーション3</button>
<button onclick="Motion(4);">モーション4</button>
<button onclick="Motion(5);">モーション5</button>
<button onclick="Motion(6);">モーション6</button>
<canvas id="my-live2d"></canvas>
<script src="live2d.js"></script>
<script src="index.js"></script> 
</body>
</html>
```
・live2dcubismcore.jsの読み込み+各種(live2d,PixiJS,kalidokit)CDNの読み込み
・表示するcanvasの定義
# live2d.js ～ライブ2D周りの設定

```javascript:live2d.js
//index.jsで使うのでスコープを外す
var app;

// PixiJS
var {
  Application, live2d: { Live2DModel }
} = PIXI;

// Kalidokit
var {
  Face, Vector: { lerp }, Utils: { clamp }
} = Kalidokit;


// 1, Live2Dモデルへのパスを指定する
var modelUrl = "./Hiyori/Hiyori.model3.json";
var currentModel;
	
// メインの処理開始
(async function main() {
  // 2, PixiJSを準備する
  app = new PIXI.Application({
    view: document.getElementById("my-live2d"),
    autoStart: true,
    backgroundAlpha: 0,
    backgroundColor: 0x0000ff,
    resizeTo: window
  });

  // 3, Live2Dモデルをロードする
  currentModel = await Live2DModel.from(modelUrl, { autoInteract: false });
  currentModel.scale.set(0.5);//モデルの大きさ★
  currentModel.interactive = true;
  currentModel.anchor.set(0.5, 0.5);//モデルのアンカー★
  currentModel.position.set(window.innerWidth/2, window.innerHeight);//モデルの位置★

  // 4, Live2Dモデルをドラッグ可能にする
  currentModel.on("pointerdown", e => {
    currentModel.offsetX = e.data.global.x - currentModel.position.x;
    currentModel.offsetY = e.data.global.y - currentModel.position.y;
    currentModel.dragging = true;
  });
  currentModel.on("pointerup", e => {
    currentModel.dragging = false;
    var updateFn = currentModel.internalModel.motionManager.update;
    var coreModel = currentModel.internalModel.coreModel;
  });
  currentModel.on("pointermove", e => {
    if (currentModel.dragging) {
      currentModel.position.set(
        e.data.global.x - currentModel.offsetX,
        e.data.global.y - currentModel.offsetY
      );
    }
  });

  // 5, Live2Dモデルを拡大/縮小可能に(マウスホイール) #my-live2dはcanvasのidにして下さい
  document.querySelector("#my-live2d").addEventListener("wheel", e => {
    e.preventDefault();
    currentModel.scale.set(
      clamp(currentModel.scale.x + event.deltaY * -0.001, -0.5, 10)
    );
  });
  //背景を設定./background.jpgを画像のパスに書きかえて下さい
  let background = PIXI.Sprite.fromImage('./background.jpg');
  background.anchor.set(0.5);
  background.x = app.screen.width / 2;
  background.y = app.screen.height / 2;
  background.height = app.screen.height;
  background.width = app.screen.width;
  app.stage.addChild(background);
  
  // 6, Live2Dモデルを配置する
  app.stage.addChild(currentModel);

})();
```
・live2dフォルダを読み込む
(フォルダ構成でmodel3.jsonあるものにして下さい)
・モデルの位置、大きさ、背景の設定
・index.jsで変数appを使うためにグローバル変数にします。
# index.js 
短いですがindex.jsは3行だけです。
```javascript:index.js
function Motion(number){
  app.stage.children[1].internalModel.motionManager.startMotion('TapBody',number,2);
}
```
HTMLのボタンで上記関数Motionを実行します。そして
live2d.jsの最初のappから階層をたどりstartMotionを起動=>該当アニメーションが再生します。
引数numberにてTapBody内から起動するアニメーション種類を指定しています。


最後にindex.htmlをローカルサーバー上で動かしてください。
(LiveServer xampp等)
![Screenshot 2022-09-22 011604.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1364047/4f6b1498-27b7-9e09-4d92-623cbc630662.png)

参考サイトhttps://zenn.dev/sdkfz181tiger/articles/df3a8bd1c3ef25
以上です。質問等ありましたら↓からコメントください。

# 以下追記
# 背景を消したい
pixi.jsのデフォルト背景と画像として差し込んだ背景と、
二つ背景があるのでそれぞれ消します！
live2d.jsを2箇所,index.jsを1箇所変更します。

デフォルト背景から、
上記live2d.jsにpixi.jsのセットアップ部分があります。
``` javascript:live2d.js
  // 2, PixiJSを準備する
  app = new PIXI.Application({
    view: document.getElementById("my-live2d"),
    autoStart: true,
    backgroundAlpha: 0,
    backgroundColor: 0x0000ff,
    resizeTo: window
  });
```
その項目に[transparent: true,]をつけ足してください。
``` javascript:live2d.js
  // 2, PixiJSを準備する
  app = new PIXI.Application({
    view: document.getElementById("my-live2d"),
    transparent: true, //この行を付け足す
    backgroundColor: 0x0000ff,
    autoStart: true,
    backgroundAlpha: 0,
    backgroundColor: 0x0000ff,
    resizeTo: window
  });
```
次に画像として差し込んだ背景を消します。
live2d.jsのファイル内で以下のように
画像を追加している部分があります。
``` javascript:live2d.js
  //背景を設定./background.jpgを画像のパスに書きかえて下さい
  let background = PIXI.Sprite.fromImage('./background.jpg');
  background.anchor.set(0.5);
  background.x = app.screen.width / 2;
  background.y = app.screen.height / 2;
  background.height = app.screen.height;
  background.width = app.screen.width;
  app.stage.addChild(background);// 画像追加しているとこ
```
この一番下のapp.stage.addChildをコメントアウトして
画像スプライトを追加しないようにします。
以下にlive2d.jsの全文を載せておきます。
``` javascript:live2d.js
 //背景を表示しないバージョン live2d.js全文
//appをindex.jsで使いたいのでスコープを外しています。
var app;

// PixiJS
var {
  Application, live2d: { Live2DModel }
} = PIXI;

// Kalidokit
var {
  Face, Vector: { lerp }, Utils: { clamp }
} = Kalidokit;


// 1, Live2Dモデルへのパスを指定する
var modelUrl = "./Hiyori/Hiyori.model3.json";
var currentModel;
	
// メインの処理開始
(async function main() {
  // 2, PixiJSを準備する
  app = new PIXI.Application({
    view: document.getElementById("my-live2d"),
    transparent: true,
    backgroundColor: 0x0000ff,
    autoStart: true,
    backgroundAlpha: 0,
    backgroundColor: 0x0000ff,
    resizeTo: window
  });

  // 3, Live2Dモデルをロードする
  currentModel = await Live2DModel.from(modelUrl, { autoInteract: false });
  currentModel.scale.set(0.5);//モデルの大きさ★
  currentModel.interactive = true;
  currentModel.anchor.set(0.5, 0.5);//モデルのアンカー★
  currentModel.position.set(window.innerWidth/2, window.innerHeight*1.1);//モデルの位置★

  // 4, Live2Dモデルをドラッグ可能にする
  currentModel.on("pointerdown", e => {
    currentModel.offsetX = e.data.global.x - currentModel.position.x;
    currentModel.offsetY = e.data.global.y - currentModel.position.y;
    currentModel.dragging = true;
  });
  currentModel.on("pointerup", e => {
    currentModel.dragging = false;
    var updateFn = currentModel.internalModel.motionManager.update;
    var coreModel = currentModel.internalModel.coreModel;
    //モーション周りのパスcurrentModel.internalModel.motionManager.startMotion('TapBody', 0,2);

  });
  currentModel.on("pointermove", e => {
    if (currentModel.dragging) {
      currentModel.position.set(
        e.data.global.x - currentModel.offsetX,
        e.data.global.y - currentModel.offsetY
      );
    }
  });

  // 5, Live2Dモデルを拡大/縮小可能に(マウスホイール) #my-live2dはcanvasのidにして下さい
  document.querySelector("#my-live2d").addEventListener("wheel", e => {
    e.preventDefault();
    currentModel.scale.set(
      clamp(currentModel.scale.x + event.deltaY * -0.001, -0.5, 10)
    );
  });
  //背景を設定./background.jpgを画像のパスに書きかえて下さい
  let background = PIXI.Sprite.fromImage('./background.jpg');
  background.anchor.set(0.5);
  background.x = app.screen.width / 2;
  background.y = app.screen.height / 2;
  background.height = app.screen.height;
  background.width = app.screen.width;
  //app.stage.addChild(background);
  
  // 6, Live2Dモデルを配置する
  app.stage.addChild(currentModel);
})();
```
# index.js 
短いですが同じく背景無しのindex.jsは3行だけです。
backgroundを消したのでapp.stageのchildrenを[1]から[0]にします。
```javascript:index.js
function Motion(number){
  app.stage.children[0].internalModel.motionManager.startMotion('TapBody',number,2);
}
```
すると背景無しの
live2dモデルを表示できるようになります。
(背景無しバージョンの動作例、コード)
デモ
https://live2dexample2--supica8219.repl.co/
コード
https://replit.com/@supica8219/Live2Dexample2#live2d.js
github
https://github.com/supica8219/Live2D_example2
![Screenshot 2022-12-18 184520.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1364047/29f848a0-0fda-5fc8-813e-6afa9c1d5789.png)

# 別のLive2Dモデルで動かしたい場合
ネックとなるのが２つあります。

まずモデルが何のLive2Dバージョンで作られているかです。
その判別方法は構成ファイルにmodel3.json,cdi3.jsonなど「3」を含むファイルが存在することです。この形のファイルを含んでいるならバージョンは大丈夫です。
例ライスグライフィールドモデル(魔法使い女の子)
https://www.live2d.com/download/sample-data/#dl_rice_pro
その他バージョンのモデルを使う場合CubismEditorで
新しいバージョンに変更し、アニメーションも一から作る必要があります。

次にアニメーションを再生するにはmodel3.jsonの"Motion"設定を見る必要があります。
以下ひよりモデルの例で説明します。
```javascript:対応するモデル(Hiyori).model3.json
"Motions": {
			"Idle": [
				{
					"File": "motions/motion1.motion3.json",
					"FadeInTime": 0.5,
					"FadeOutTime": 0.5
				}
			],
			"TapBody": [
				{
					"File": "motions/motion1.motion3.json",
					"FadeInTime": 0.5,
					"FadeOutTime": 0.5
				},
				{
					"File": "motions/motion2.motion3.json",
					"FadeInTime": 0.5,
					"FadeOutTime": 0.5
				},
				{
					"File": "motions/motion3.motion3.json",
					"FadeInTime": 0.5,
					"FadeOutTime": 0.5
				}
			]
		}
```
Motionsの中にIdleとTapBodyという塊があります。その中に
"File" アニメーションを一つ定義するファイルmotion3.jsonへのパス
"FadeInTime","FadeOutTime"が幾つか入っています。
入っていない場合はどうしようもないのでcubismEditorで作るしかないです。
IdleはLive2D待機時のモーション群,TapBodyは指定されたタイミングのアクション群です。
前述のindex.jsではTapBodyのnumber版目のアニメーションを再生していました。
```javascript:index.js
function Motion(number){
app.stage.children[0].internalModel.motionManager.startMotion('TapBody',number,2);
}
```