物体をドラッグするのに、DragControl
というのが使える。
ということが分かったのでやってみました。
この辺の記事を参考にしました。
この箱をドラッグして動かせるようにする。
以前の掲載した、この記事のコードをベースに、
(上記の記事の最初に掲載されているコードに対して、)
importsに、three/addons/ を追加する。
<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 する。
<script type="module">
import * as THREE from "three";
import { DragControls } from "three/addons/controls/DragControls.js";
「レンダラーを作成」の部分は、もともと以下のコードでしたが、
// レンダラーを作成
const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector("#myCanvas"),
});
後でDragControlsの引数として使うので、変数canvasElementを作成してから設定するように変更。
// レンダラーを作成
const canvasElement = document.querySelector("#myCanvas");
const renderer = new THREE.WebGLRenderer({
canvas: canvasElement,
});
なんとなく箱が大きすぎて見にくいと思ったので、もともと400,400,400でしたが、300,300,300に変更。
(ここは変更してもしなくてもよい)
// 箱を作成
const geometry = new THREE.BoxGeometry(300, 300, 300);
「箱を作成」後に、「ドラッグコントローラーを作成」以下のコードを追加する。
// 箱を作成
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);
これで実行すると、
初めは箱は中心にあるのですが、
ドラッグして下とか、上とかに移動できるようになりました!
CodePen で書いた
See the Pen three.js 入門 5_1 by sasuke (@vhmbdiog-the-flexboxer) on CodePen.
ハマった点
ここでハマったのが、「DragControlsの第1引数は配列じゃないとだめ」っていうこと。
今回はboxが1個だけですが、第1引数がboxだとエラーで動きません。
const controls_drag = new DragControls(box, camera, canvasElement);
こうする必要があります。
let objects = [box]; //第1引数は配列じゃないとだめ。
const controls_drag = new DragControls(objects, camera, canvasElement);
複数の物体(object)を動かす場合は、それらを配列にして入れられるようになっているらしいです。
公式ドキュメントには、第1引数の定義は、
objects: An array of draggable 3D objects.
と書いてあります。
コード全体
<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>
箱を複数個にしてみる。
「箱を作成」の部分を変更して、箱を複数にしてみる。
// 箱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] にして入れる。
// ドラッグコントローラーを作成
let objects = [box1, box2, box3]; //第1引数は配列じゃないとだめ。
const controls_drag = new DragControls(objects, camera, canvasElement);
初期位置
ドラッグで動かすと、こんな感じで動かせる。
CodePen で書いた
See the Pen three.js 入門 5_2 by sasuke (@vhmbdiog-the-flexboxer) on CodePen.