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); } }