2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[Three.js] 物体をドラッグしてみる

Posted at

物体をドラッグするのに、DragControl というのが使える。
ということが分かったのでやってみました。

この辺の記事を参考にしました。

この箱をドラッグして動かせるようにする。

22.PNG

以前の掲載した、この記事のコードをベースに、

(上記の記事の最初に掲載されているコードに対して、)
importsに、three/addons/ を追加する。

html
    <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>

DragControls を import する。

html
    <script type="module">
      import * as THREE from "three";
      import { DragControls } from "three/addons/controls/DragControls.js";

「レンダラーを作成」の部分は、もともと以下のコードでしたが、

html(変更前)
      // レンダラーを作成
      const renderer = new THREE.WebGLRenderer({
        canvas: document.querySelector("#myCanvas"),
      });

後でDragControlsの引数として使うので、変数canvasElementを作成してから設定するように変更。

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

なんとなく箱が大きすぎて見にくいと思ったので、もともと400,400,400でしたが、300,300,300に変更。
(ここは変更してもしなくてもよい)

html
      // 箱を作成
      const geometry = new THREE.BoxGeometry(300, 300, 300);

「箱を作成」後に、「ドラッグコントローラーを作成」以下のコードを追加する。

html
      // 箱を作成
      const geometry = new THREE.BoxGeometry(300, 300, 300);
      const material = new THREE.MeshNormalMaterial();
      const box = new THREE.Mesh(geometry, material);
      scene.add(box);

      // ドラッグコントローラーを作成

      let objects = [box]; //第1引数は配列じゃないとだめ。
      const controls_drag = new DragControls(objects, camera, canvasElement);

これで実行すると、
初めは箱は中心にあるのですが、

23.PNG

ドラッグして下とか、上とかに移動できるようになりました!

24.PNG

25.PNG

CodePen で書いた

See the Pen three.js 入門 5_1 by sasuke (@vhmbdiog-the-flexboxer) on CodePen.

ハマった点

ここでハマったのが、「DragControlsの第1引数は配列じゃないとだめ」っていうこと。

今回はboxが1個だけですが、第1引数がboxだとエラーで動きません。

html
      const controls_drag = new DragControls(box, camera, canvasElement);

こうする必要があります。

html
      let objects = [box]; //第1引数は配列じゃないとだめ。
      const controls_drag = new DragControls(objects, camera, canvasElement);

複数の物体(object)を動かす場合は、それらを配列にして入れられるようになっているらしいです。

公式ドキュメントには、第1引数の定義は、

objects: An array of draggable 3D objects.

と書いてあります。

コード全体

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 { DragControls } from "three/addons/controls/DragControls.js";

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

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

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

      // カメラを作成
      const camera = new THREE.PerspectiveCamera(45, width / height);
      camera.position.set(0, 0, +1000);

      // 箱を作成
      const geometry = new THREE.BoxGeometry(300, 300, 300);
      const material = new THREE.MeshNormalMaterial();
      const box = new THREE.Mesh(geometry, material);
      scene.add(box);

      // ドラッグコントローラーを作成

      //第1引数は配列じゃないとだめ。
      let objects = [box]; //これがないとだめ
      const controls_drag = new DragControls(objects, camera, canvasElement);

      tick();

      // 毎フレーム時に実行されるループイベントです
      function tick() {
        box.rotation.y += 0.01;
        renderer.render(scene, camera); // レンダリング

        requestAnimationFrame(tick);
      }
    </script>
  </head>
  <body>
    <canvas id="myCanvas"></canvas>
  </body>
</html>

箱を複数個にしてみる。

「箱を作成」の部分を変更して、箱を複数にしてみる。

html
      // 箱1を作成
      const geometry = new THREE.BoxGeometry(300, 300, 300);
      const material = new THREE.MeshNormalMaterial();
      const box1 = new THREE.Mesh(geometry, material);
      scene.add(box1);

      // 箱2を作成
      const geometry2 = new THREE.BoxGeometry(200, 200, 200);
      const box2 = new THREE.Mesh(geometry2, material);
      //場所を変える
      box2.position.x = 400;
      box2.position.z = 400;
      scene.add(box2);

      // 箱3を作成
      const geometry3 = new THREE.BoxGeometry(100, 100, 100);
      const box3 = new THREE.Mesh(geometry2, material);
      //場所を変える
      box3.position.x = -600;
      box3.position.z = -400;
      scene.add(box3);

「ドラッグコントローラーを作成」の部分は、第1引数を配列 [box1, box2, box3] にして入れる。

html
      // ドラッグコントローラーを作成
      let objects = [box1, box2, box3]; //第1引数は配列じゃないとだめ。
      const controls_drag = new DragControls(objects, camera, canvasElement);

初期位置

26.PNG

ドラッグで動かすと、こんな感じで動かせる。

27.PNG

28.PNG

CodePen で書いた

See the Pen three.js 入門 5_2 by sasuke (@vhmbdiog-the-flexboxer) on CodePen.

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?