[Three.js] 物体を奥行きの方向にも移動させる。

前回の記事は、`DragControls`  を使って、物体をドラッグしましたが、

https://qiita.com/sasuke_sss/items/2600166bc3b1cad1177a

`DragControls` を使ったこのやり方だと、物体を平面的に移動させることしかできない。
奥行きの方向にはドラッグできない。

奥行きの方向にも移動させたいと思って調べていたら、
`TransformControls`を使えばできるらしいと分かった。

https://qiita.com/naotaro0123/items/58b767ac832e8ddd4520

`TransformControls`だけだと、カメラの視点移動ができないので、
`OrbitControls`も使っています。
(視点移動できないと、物体位置を把握しにくいので、カメラ視点移動も使えるようにします)

また、奥方向に移動したかどうか、わかりやすくするために、
軸`AxesHelper`とグリッド`GridHelper`も表示させています。
（動かない基準が何も無いと、物体がどこに動いたのかわからなくなるので）

上記の記事を参考に、`TransformControls`、`OrbitControls`を設定。
#### コード
```html:html
<html>
  <head>
    <meta charset="utf-8" />
    <script type="importmap">
      {
        "imports": {
          "three": "https://cdn.jsdelivr.net/npm/three@0.164.1/build/three.module.js",
          "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.164.1/examples/jsm/"
        }
      }
    </script>
    <script type="module">
      import * as THREE from "three";
      import { OrbitControls } from "three/addons/controls/OrbitControls.js";
      import { TransformControls } from "three/addons/controls/TransformControls.js";


      // サイズを指定
      const width = 960;
      const height = 540;

      // レンダラーを作成
      const canvasElement = document.querySelector("#myCanvas");
      const renderer = new THREE.WebGLRenderer({
        canvas: canvasElement,
      });
      renderer.setSize(width, height);

      // シーンを作成
      const scene = new THREE.Scene();

      // カメラを作成
      const camera = new THREE.PerspectiveCamera(45, width / height, 1, 3000);
      // カメラの初期座標を設定
      camera.position.set(500, 1000, 1500);

      // カメラコントローラーを作成
      const orbitControls = new OrbitControls(camera, canvasElement);
      orbitControls.update();
      orbitControls.addEventListener('change', tick);

      // 形状とマテリアルからメッシュを作成します
      const mesh = new THREE.Mesh(new THREE.BoxGeometry(300, 300, 300), new THREE.MeshNormalMaterial({ transparent: true }));
      scene.add(mesh);

      // TransformControls　コントローラーを作成
      const transControls = new TransformControls(camera, canvasElement);
      transControls.addEventListener('change', tick);
      transControls.attach(mesh);

      //軸を追加する。
      const axesHelper = new THREE.AxesHelper( 1000 );
      scene.add( axesHelper );

      //グリッドを追加する。
      const gridHelper = new THREE.GridHelper(2000, 50, 0xffff00) 
      scene.add(gridHelper);

      transControls.addEventListener('dragging-changed', event => {
        orbitControls.enabled = !event.value;
      });
      scene.add(transControls);
      setShotrCutKey();
      tick();

      function setShotrCutKey() {
        window.addEventListener('keydown', event => {
          switch (event.keyCode) {
            case 87: // W = translate
              transControls.setMode('translate');
              break;
            case 69: // E = rotate
              transControls.setMode('rotate');
              break;
            case 82: // R = scale
              transControls.setMode('scale');
              break;
          }
        });
      }

      // 毎フレーム時に実行されるループイベントです
      function tick() {
        // レンダリング
        renderer.render(scene, camera);
        requestAnimationFrame(tick);
      }
    </script>
  </head>
  <body>
    <canvas id="myCanvas"></canvas>
  </body>
</html>
```
初期画面表示
![49.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/8efed2c0-c296-2a4f-7072-3efe6a62a75b.png)

箱に矢印のUI（x, y, z方向）が表示されています。
x, y, z の矢印にカーソルをあわせてからドラッグすると
それぞれの方向に移動できます。

![29.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/7195308e-d311-e614-5715-8b7c88f950be.png)

![30.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/7a7e6ee2-c82d-3eeb-0027-20c7f28231e2.png)
![31.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/5d783dcb-4d94-ac4a-aef2-d162a17734e6.png)

# 移動
### 1. 左から右に移動
![36.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/560f0710-ed22-5c63-28a2-108bef87ca71.png)
![37.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/7eb2ccf9-caee-d210-69e7-c1e57874c1fe.png)

### 2. 奥から手前に移動
![38.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/b1fe979a-124b-6196-583c-10cc78108df6.png)
![39.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/50b68a50-bc1d-28b2-1819-7e9dd78ecac2.png)

### 3. 右から真ん中に移動
![40.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/a9bd2a5a-6f6a-7c93-932e-05050de23610.png)
![41.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/39c525be-0f93-8301-b516-6782a00c85e9.png)

### 4. 垂直に上に移動
![42.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/e7916ab0-431d-8539-22ca-931c19d37758.png)
![43.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/34bf6f1f-fbec-856d-7651-2efda84b4bef.png)

# 回転
`TransformControls`を使えば、移動だけでなく、回転もできる。

キーボードで、E を押すと、UIのガイドが、円に変化し、回転させることができる。

![44.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/21b33ec8-0694-9ea2-0a25-2262deb75e1b.png)

![45.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/1e5b8ecf-b089-4220-c1e1-d40e3ad2c0aa.png)

# 拡大縮小
Rを押すと、また、ガイドが変わり、

![46.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/b3e2b5ad-51fe-62d6-6ddb-85f27438a267.png)

(ある方向について)、縮めたり、

![47.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/8a955088-3f0f-7f5f-f8c9-81d7515b297a.png)

(ある方向について)、伸ばしたりできます。

![48.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/0c490ecc-e468-f7c7-c9d0-e6da4eb075de.png)

# CodePenで書いた

<p class="codepen" data-height="700" data-default-tab="html,result" data-slug-hash="QwLrgbv" data-pen-title="three.js 入門 6_1" data-user="vhmbdiog-the-flexboxer" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/vhmbdiog-the-flexboxer/pen/QwLrgbv">
  three.js 入門 6_1</a> by sasuke (<a href="https://codepen.io/vhmbdiog-the-flexboxer">@vhmbdiog-the-flexboxer</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>