threejs9 框选模型

按住空格键control.enabled=false,框选模型变成红色。

/**
 * 框选
 */

import * as THREE from "three"
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"
import { AmbientLight, AxesHelper, BoxBufferGeometry, DirectionalLight, HemisphereLight, Mesh, MeshPhongMaterial, SphereGeometry, TextureLoader } from "three";
import{GLTFLoader}from "three/examples/jsm/loaders/GLTFLoader"
import{SelectionBox}from "three/examples/jsm/interactive/SelectionBox"
import{SelectionHelper}from "three/examples/jsm/interactive/SelectionHelper"

var renderer = new THREE.WebGLRenderer({ antialias: true });
// renderer.domElement;//是一个canvas 可以从参数传入
document.body.appendChild(renderer.domElement);

renderer.setSize(window.innerWidth, window.innerHeight);//设置画布高宽
renderer.setClearColor(0xffffff);//设置背景清空颜色

window.addEventListener("resize", () => {//窗口大小变化事件
    renderer.setSize(window.innerWidth, window.innerHeight);
    camera.aspect = window.innerWidth / window.innerHeight;
    //设置了aspect  必须更新相机的投影矩阵
    camera.updateProjectionMatrix();
})

var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 2, 100)
var control = new OrbitControls(camera, renderer.domElement);
var scene = new THREE.Scene();

scene.background = new THREE.CubeTextureLoader()
    .setPath( "../assets/textures/cubeMaps/")
    .load( [
        'posx.jpg',
        'negx.jpg',
        'posy.jpg',
        'negy.jpg',
        'posz.jpg',   
        'negz.jpg'
    ] );


var dirLight=new DirectionalLight(0xffffff);
dirLight.intensity=5;

var light = new HemisphereLight(0xffffff, 0x444444);
scene.add(light);
scene.add(dirLight);

//---------------------生成1000个随机立方体-------------------------------------
var cubeGrometry=new BoxBufferGeometry(2,2,2);
for (let i = 0; i < 1000; i++) {
    //Math.random()生成一个0-1之间的随机数
    var mesh=new Mesh(cubeGrometry,new MeshPhongMaterial({color:0xffffff*Math.random()}))
    scene.add(mesh);
    mesh.position.set(300*Math.random()-50,300*Math.random()-50,300*Math.random()-50);
    mesh.scale.set(2*Math.random()+1,2*Math.random()+1,2*Math.random()+1);
    mesh.rotation.set(7*Math.random(),7*Math.random(),7*Math.random());
}
//---------------------------框选---------------------------------------
var raycaster =new THREE.Raycaster();
var coords=new THREE.Vector2(0,0);

var selectedMaterial=new MeshPhongMaterial({color:0xff0000});

var lastSelectModel=null;

/**
 * 选中包围盒
 * SelectionBox(camera: THREE.Camera, scene: THREE.Scene, deep?: number)
 * SelectionBox.collection 表示选中的几何
 */
 var selectedBox = new SelectionBox(camera, scene);
 var selectedHelper = new SelectionHelper(selectedBox, renderer, "selectBox");
 var allowBoxSelectd = true;
 
 window.addEventListener("keydown", (ev) => {
     control.enabled=false;
     if (ev.key == " ") {
         allowBoxSelectd = !allowBoxSelectd;
         if (allowBoxSelectd)
             selectedHelper.element.style.display = ""
         else {
             selectedHelper.element.style.display = "none"
         }
     }
 })
 
 window.addEventListener("pointerdown", (ev) => {
     if (allowBoxSelectd) {
         var x = (ev.clientX / window.innerWidth) * 2 - 1;
         var y = -(ev.clientY / window.innerHeight) * 2 + 1;
 
         //清空状态 
         for (let i = 0; i < selectedBox.collection.length; i++) {
             var oneSelectedModel = selectedBox.collection[i];
             oneSelectedModel.material = oneSelectedModel.orgMaterial
         }
 
         selectedBox.startPoint.set(x, y, 0.5);
 
     }
 })
 
 window.addEventListener("pointermove", (ev) => {
 
     if (allowBoxSelectd && selectedHelper.isDown) {
         control.enabled = false
         var x = (ev.clientX / window.innerWidth) * 2 - 1;
         var y = -(ev.clientY / window.innerHeight) * 2 + 1;
 
         selectedBox.endPoint.set(x, y, 0.5);
 
         selectedBox.select();
 
         // console.log(selectedBox.collection)
 
         for (let i = 0; i < selectedBox.collection.length; i++) {
             var oneSelectedModel = selectedBox.collection[i];
             if (!oneSelectedModel.orgMaterial)
                 oneSelectedModel.orgMaterial = oneSelectedModel.material;
 
             oneSelectedModel.material = selectedMaterial
         }
 
     } else {
         control.enabled = true;
     }
 
 })
 
 window.addEventListener("pointerup", (ev) => {
 
     if (allowBoxSelectd) {
         control.enabled = false
         var x = (ev.clientX / window.innerWidth) * 2 - 1;
         var y = -(ev.clientY / window.innerHeight) * 2 + 1;
 
         selectedBox.endPoint.set(x, y, 0.5);
 
         selectedBox.select();
 
 
         for (let i = 0; i < selectedBox.collection.length; i++) {
             var oneSelectedModel = selectedBox.collection[i];
             //必须先判断是否备份原始材质
             if (!oneSelectedModel.orgMaterial)
                 oneSelectedModel.orgMaterial = oneSelectedModel.material;
             oneSelectedModel.material = selectedMaterial
         }
 
         if (selectEvent.onSelectd)
             selectEvent.onSelectd(selectedBox.collection);
 
     }
 })
//--------------------------------END----------------------------------------
update()

function update() {
    console.log('刷新')
    renderer.render(scene, camera);
    requestAnimationFrame(update);//不会卡塞,专门针对图形渲染刷新的方法
}

//-------------------------模型加载--------------------------------
var gltfLoader=new GLTFLoader();
gltfLoader.load("../assets/models/glTF/wuren.glb",(glb)=>{
glb.scene.x=-10;
// glb.scale.set(10,10,10);
    scene.add(glb.scene);
});

效果图:
在这里插入图片描述

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
three.js中实现框选功能可以通过以下步骤来实现: 1. 创建一个框选区域:通过鼠标事件监听用户的鼠标按下、移动和释放动作,记录下鼠标按下的位置和移动的位置,根据这两个位置计算出框选区域的位置和大小。 2. 射线检测:使用three.js提供的射线检测功能,将框选区域转换为一个射线,然后与场景中的物体进行相交检测。可以使用`Raycaster`类来进行射线检测。 3. 获取选中的物体:根据射线检测的结果,可以获取到与框选区域相交的物体。可以通过遍历射线检测的结果,获取到选中的物体。 下面是一个示例代码,演示了如何在three.js中实现框选功能: ```javascript // 创建一个框选区域 var boxSelect = document.createElement('div'); boxSelect.style.position = 'absolute'; boxSelect.style.border = '1px dashed red'; boxSelect.style.pointerEvents = 'none'; document.body.appendChild(boxSelect); var mouseDown = false; var startMousePos = new THREE.Vector2(); var endMousePos = new THREE.Vector2(); // 监听鼠标按下事件 document.addEventListener('mousedown', function(event) { mouseDown = true; startMousePos.x = (event.clientX / window.innerWidth) * 2 - 1; startMousePos.y = -(event.clientY / window.innerHeight) * 2 + 1; }); // 监听鼠标移动事件 document.addEventListener('mousemove', function(event) { if (mouseDown) { endMousePos.x = (event.clientX / window.innerWidth) * 2 - 1; endMousePos.y = -(event.clientY / window.innerHeight) * 2 + 1; // 更新框选区域的位置和大小 var boxWidth = Math.abs(endMousePos.x - startMousePos.x); var boxHeight = Math.abs(endMousePos.y - startMousePos.y); boxSelect.style.left = Math.min(startMousePos.x, endMousePos.x) * 100 + '%'; boxSelect.style.top = Math.min(startMousePos.y, endMousePos.y) * 100 + '%'; boxSelect.style.width = boxWidth * 100 + '%'; boxSelect.style.height = boxHeight * 100 + '%'; } }); // 监听鼠标释放事件 document.addEventListener('mouseup', function(event) { mouseDown = false; // 将框选区域转换为射线 var raycaster = new THREE.Raycaster(); raycaster.setFromCamera(startMousePos, camera); // 进行射线检测 var intersects = raycaster.intersectObjects(scene.children, true); // 获取选中的物体 var selectedObjects = []; for (var i = 0; i < intersects.length; i++) { selectedObjects.push(intersects[i].object); } // 处理选中的物体 // ... }); ``` 请注意,上述代码中的`camera`和`scene`是需要根据你的具体场景进行替换的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值