import * as THREE from 'three';
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { DragControls } from "three/examples/jsm/controls/DragControls";
/**
* 3d Controls 控制器,拖放
* https://threejs.org/docs/index.html#examples/zh/controls/DragControls
*/
export class ThreeDoc9ControlDrag {
constructor(canvasId) {
this.work(canvasId);
}
work(canvasId) {
// 创建 3d 场景
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x9e9e9e);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
// 最后一步很重要,我们将renderer(渲染器)的dom元素(renderer.domElement)添加到我们的HTML文档中。这就是渲染器用来显示场景给我们看的<canvas>元素。
document.body.appendChild(renderer.domElement);
// 开启阴影
renderer.shadowMap.enabled = true
// AxesHelper 3个坐标轴的对象.
this.addAxesHelper(scene);
// 半球光(HemisphereLight)
this.addHemisphereLight(scene);
// 网格辅助对象
let size = 20;
const gridHelper = new THREE.GridHelper( size, 10 , 0x444444, 0xffffff);
scene.add( gridHelper );
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// 设置相机位置
camera.position.x = 5;
camera.position.y = 6;
camera.position.z = 15;
camera.lookAt(0, 0, 0);
// 添加控制器
let orb = new OrbitControls(camera, document.body);
orb.addEventListener('change', function () {
renderer.render(scene, camera);
});
// 添加物体
let geometry = new THREE.BoxGeometry(2, 2, 2);
let material = new THREE.MeshStandardMaterial({ color: 0x049EF4 });
let obj = new THREE.Mesh(geometry, material);
obj.position.set(0, 1, 0);
scene.add(obj);
let arr = [obj];
// 拖拽控制器,将可拖拽的物体,以数组形式传入
const controls = new DragControls(arr, camera, renderer.domElement);
/**
* 事件
* dragstart : 当用户开始拖拽3D Objects时触发。
* drag : 当用户拖拽3D Objects时触发。
* dragend : 当用户开始完成3D Objects时触发。
* hoveron: 当指针移动到一个3D Object或者其某个子级上时触发。
* hoveroff : 当指针移出一个3D Object时触发。
*/
controls.addEventListener('dragstart', function (event) {
orb.enabled = false;
});
controls.addEventListener('drag', function (event) {
event.object.material.emissive.set(0xaaaaaa);
console.log(event);
renderer.render(scene, camera);
});
controls.addEventListener('dragend', function (event) {
orb.enabled = true;
event.object.material.emissive.set(0x000000);
renderer.render(scene, camera);
});
// 添加第二个物体
let geometry2 = new THREE.SphereGeometry(1, 32, 16);
let material2 = new THREE.MeshStandardMaterial({ color: 0x049EF4 });
let obj2 = new THREE.Mesh(geometry2, material2);
obj2.position.set(5, 1, 5);
scene.add(obj2);
// 直接操作可拖拽对象的数组,即可添加。这也太方便了吧
arr.push(obj2);
/**
* Methods
* .activate () : undefined
* 添加控制器的事件监听。
* .deactivate () : undefined
* 移除控制器的事件监听。
* .dispose () : undefined
* 若不再需要该控制器,则应当调用此函数。
* .getObjects () : Array
* Returns the array of draggable objects.
* .getRaycaster () : Raycaster
* Returns the internal Raycaster instance that is used for intersection tests.
*/
renderer.render(scene, camera);
}
/**
* AxesHelper
* 用于简单模拟3个坐标轴的对象.
* 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
* AxesHelper( size : Number )
* size -- (可选的) 表示代表轴的线段长度. 默认为 1.
*/
addAxesHelper(scene) {
const axesHelper = new THREE.AxesHelper(12);
scene.add(axesHelper);
}
/**
* 半球光(HemisphereLight) - 喜欢这个光
* 光源直接放置于场景之上,光照颜色从天空光线颜色渐变到地面光线颜色。
* 半球光不能投射阴影。
*
* HemisphereLight( skyColor : Integer, groundColor : Integer, intensity : Float )
* skyColor - (可选参数) 天空中发出光线的颜色。 缺省值 0xffffff。
* groundColor - (可选参数) 地面发出光线的颜色。 缺省值 0xffffff。
* intensity - (可选参数) 光照强度。 缺省值 1。
*/
addHemisphereLight(scene) {
const light = new THREE.HemisphereLight(0xffffbb, 0x080820, 50);
scene.add(light);
light.position.set(0, -20, 0);
// const helper = new THREE.HemisphereLightHelper(light, 3);
// scene.add(helper);
}
}