はてなブログにThree.jsで3Dモデルを表示してみる。

# はてなブログに3Dモデルを表示したい
## 結論から先に
[動いているところ](https://wakagomo.hatenablog.jp/entry/2019/01/13/152638)
[ソースコード](#はてなブログに3dモデルを表示する)

## はじめに
趣味で作成した美少女の3Dモデルを、はてなブログ（[うつで死にそう](https://wakagomo.hatenablog.jp/)）に**画像**で投稿している。
まだ一週間も経ってないけど、0アクセスが続いているのは悲しい・・・
![view.png](https://qiita-image-store.s3.amazonaws.com/0/341662/1698ba08-98d2-2733-348f-7be77986d204.png)
## 3Dモデルを表示してかっこよくしたい
3Dモデルを表示できれば画像ぺたぺたのブログよりイケてるブログができるんじゃないだろうか。
そうすれば、アクセス数も増えるんじゃないだろうか。

・・・そんな邪な気持ちで、はてなブログに3Dモデルを表示していこうと思う。

# はてなブログでThree.jsを使ってみる
まずは3Dモデルの表示を抜きにしたThree.jsを試してみる、これができなきゃ話にならない。
以下のコードをHTML編集のテキストボックスに打ち込む。

```html:sample.html
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/100/three.min.js"></script>
<script>
  window.addEventListener("load", init)

  function init() {
    // キャンバスサイズ
    const width = 512
    const height = 512

    // レンダラーの作成
    const renderer = new THREE.WebGLRenderer({ canvas: document.querySelector("canvas") })
    renderer.setPixelRatio(window.devicePixelRatio)
    renderer.setSize(width, height)
    // シーンの作成
    const scene = new THREE.Scene()
    // カメラの作成
    const camera = new THREE.PerspectiveCamera(45, width / height)
    
    // 箱の作成
    const geometry = new THREE.BoxGeometry(10, 10, 10)
    const material = new THREE.MeshNormalMaterial()
    const box = new THREE.Mesh(geometry, material)
    scene.add(box)
    
    // レンダリング
    camera.position.set(100, 100, 100)
    camera.lookAt(box.position)
    renderer.render(scene, camera)
  }
</script>
<canvas id="canvas"></canvas>
```

## 表示結果
![sample.png](https://qiita-image-store.s3.amazonaws.com/0/341662/26d99071-e4c3-8747-ccc8-e8875fb01fad.png)
できてる！！
これができるってことは、あと少しで3Dモデルを表示できそう。

# はてなブログに3Dモデルを表示する
同じく、以下のコードをHTML編集に打ち込む。

```html:sample.html
<input id="view" type="button" value="3Dモデルを表示する" />（※表示に5秒前後かかるよ）<br>
<canvas id="three"></canvas><br>

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/100/three.min.js"></script>
<script src="https://dl.dropboxusercontent.com/s/wtcer7wh4pz0sxj/OBJLoader.js"></script>
<script src="https://dl.dropboxusercontent.com/s/i3exk9p5ddeuokq/OrbitControls.js"></script>
<script type="text/javascript">
  document.getElementById("view").addEventListener("click", init);
  
  function init() {
    // キャンバスサイズ
    const width = 512
    const height = 512

    // レンダラーの作成
    const renderer = new THREE.WebGLRenderer({ canvas: document.querySelector("#three") })
    renderer.setPixelRatio(window.devicePixelRatio)
    renderer.setSize(width, height)
    renderer.setClearColor(new THREE.Color(0xffffff))
    // シーンの作成
    const scene = new THREE.Scene()
    // カメラの作成
    const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 10000)
    camera.position.set(0, 0, 100)
    // カメラコントローラの作成
    const controls = new THREE.OrbitControls(camera)

    // OBJファイルの読み込み
    const loader = new THREE.OBJLoader()
    loader.load("https://dl.dropboxusercontent.com/s/nvm2xo3am3kx8eu/bishojo5.OBJ",
      (object) => {
        // 読み込み後シーンに追加
        object.position.set(0, 25, 0)
        object.scale.set(25, 25, 25)
        scene.add(object)

        renderer.render(scene, camera)
      })

    animation()
    // カメラコントロールを反映させる、描画処理
    function animation() {
      renderer.render(scene, camera)
      requestAnimationFrame(animation)
    }
  }
</script>
```

## 表示結果
![sample2.png](https://qiita-image-store.s3.amazonaws.com/0/341662/d6396c55-6976-f350-4e17-e0dd606673be.png)
できた！！！！！
テクスチャとかマテリアルの設定してないので、真っ黒だけど360度どの方向からも見ることができる。
## 確認した環境
Chrome(Windows)では（おそらく）問題なく表示できた。
が、スマホのSafari(iOS)では縦のフリックがスクロールに吸われてうまく表示の回転ができなかった。スマホに対応するときは画面のスクロールを制限したりの対策が必要かもしれない（はてなブログでできるかは知らない）

# 余談
## ファイルの置き場所
一番これが困ったんだけど、はてなブログでは画像以外のファイルのアップロードができなかった。つまり、JavaScriptのソースはもちろん、3Dモデルファイルもアップロードできない。
しかたがないので、GoogleDriveの一般公開でごまかしながら実装しようとしたら、**CORS**で弾き飛ばされた。
どうしたもんかと思ったが、DropBoxのアカウント作ってDropBoxの共有リンクで実装したら何とか動いた。

モデルの読み込みには**OBJLoader.js**が必要なんだけど、これも**Three.js**と同じくホットリンクで処理したかったが、Node.js用のCDNしかなく断念した。
## はてなブログとJavaScript
当然の如くはてなブログでのスクリプト編集は予測効かなかったり、プレビュー挟まないと表示の確認ができなかったりで骨が折れる。Three.jsのお試しで箱を表示した時点で結構萎えた。正直言って、もうやりたくない・・・

あと、はてなブログに限った話ではないかもしれないが、CORSとかButtonに直接onClick使えなかったりは、JavaScriptにわかの自分にはぶっ刺さった（半日ぐらい消費した）。
# 終わりに
初投稿なのでお作法的に至らない点とか、規約的に危ない箇所があれば教えてください。素早く修正したいと思います。

実際に動いているところは[美少女作るお　その５．５　～3Dモデルを表示してみる～](https://wakagomo.hatenablog.jp/entry/2019/01/13/152638)で見ることができるので、よかったら見てみてください。