threejs创建多个立方体,并支持鼠标点击选中

threejs创建多个立方体,并支持鼠标点击选中


  • threejs创建多个立方体并支持鼠标点击选中
    • 引入所需的插件
    • 创建渲染器Renderer
    • 创建相机Camera
    • 创建视图控制器OrbitControls
    • 创建场景Scene
    • 创建辅助坐标轴AxisHelper
    • 添加地面网格GirdHelper
    • 添加空间正方体BoxGeometry Mesh
    • 添加光投射器Raycaster
    • 执行渲染
    • 效果图
    • 完整代码

引入所需的插件

<script src="https://cdn.bootcss.com/three.js/r83/three.min.js">script>

<script src="libs/OrbitControls.js">script>

创建渲染器Renderer

把三维的场景渲染到显示屏上

renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth,window.innerHeight);
//container:浏览器画图区域对应的dom元素
container.appendChild(renderer.domElement);

创建相机Camera

相当于人的眼睛,看到物体的大小远近与相机的位置和设置有关

/*
        创建相机【远景相机,与人眼观察类似,近大远小】
        param1:视角【视角越大  物体渲染到屏幕时则看着越小,反之越大】
        param2:相机拍摄面的长宽比
        param3:近裁剪面,相机与物体的距离小于该值后将不在屏幕上显示
        param4:远裁剪面,相机与物体的距离大于该值后将不在屏幕上显示
*/
camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,2000);
camera.position.set(10,10,800);

创建视图控制器OrbitControls

通过鼠标拖动和滑轮移动自动改变相机的位置,调整视角,重新渲染页面

controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render );

创建场景Scene

用于添加空间范围内需要显示的物体

scene = new THREE.Scene();
scene.background = new THREE.Color(0xf0f0f0);

创建辅助坐标轴AxisHelper

通过 X(屏幕右边) 、 Y(屏幕上边) 、 Z(屏幕由内到外) 三条轴线帮助你了解物体空间位置坐标

var axes = new THREE.AxisHelper(800);//参数设置了三条轴线的长度
scene.add(axes);

添加地面网格GirdHelper

在指定位置条件指定长度、数量的网格图形

/**
 * size 网格总边长
 * step 网格个数
 * colorCenterLine  网格中心线颜色
 * colorGrid    网格其他线颜色
 */
var gridHelper = new THREE.GridHelper( 300, 10, 'red', 'gray' );
gridHelper.position.y = -100;
gridHelper.position.x = 0;
scene.add( gridHelper );

添加空间正方体BoxGeometry Mesh

var geometry = new THREE.BoxGeometry(20,20,20);//盒子模型
for ( var i = 0; i < 100; i ++ ) {
    var material = new THREE.MeshBasicMaterial({color:"gray"});//材料
    var mesh = new THREE.Mesh( geometry, material );
    mesh.position.x = ( Math.random() - 0.5 ) * 1000;
    mesh.position.y = ( Math.random() - 0.5 ) * 1000;
    mesh.position.z = ( Math.random() - 0.5 ) * 1000;
    scene.add( mesh );
}

添加光投射器Raycaster

通过光投射器结合鼠标位置坐标,判断鼠标是否经过物体

raycaster = new THREE.Raycaster();//光线投射器
mouse = new THREE.Vector2();//二维向量 
document.addEventListener('mousemove', function(){
    event.preventDefault();
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
}, false);

var projectiveObj;//定义上次投射到的对象
/**
 * 根据光投射器判断鼠标所在向量方向是否穿过物体
 * @param {*} raycaster 光投射器
 * @param {*} scene     场景
 * @param {*} camera    相机
 * @param {*} mouse     鼠标位置对应的二维向量
 */
function renderRaycasterObj(raycaster,scene,camera,mouse) {
    raycaster.setFromCamera(mouse, camera);
    var intersects = raycaster.intersectObjects(scene.children);
    if (intersects.length > 0) {
        var currentProjectiveObjT = intersects[0].object;
        if (projectiveObj != currentProjectiveObjT) {
            if((currentProjectiveObjT instanceof THREE.AxisHelper) || (currentProjectiveObjT instanceof THREE.GridHelper)){
                //穿过的是坐标轴线和网格线
                return;
            }
            projectiveObj = intersects[0].object;
        }
    } else {
        projectiveObj = null;
    }
}

执行渲染

function render() {

    requestAnimationFrame(render);

    renderRaycasterObj(raycaster,scene,camera,mouse);//渲染光投射器投射到的对象

    renderer.render( scene, camera);

}

效果图

threejs创建多个立方体,并支持鼠标点击选中_第1张图片

完整代码


<html lang="en">
    <head>
        <title>创建threejs场景-旋转的立方体title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <style>
            body{margin: 0}
            canvas{width: 100% ; height: 100%}
            div#drawArea{
                position: fixed;
            }
        style>
    head>
    <body>

        <div id="drawArea">div>

        <script src="https://cdn.bootcss.com/three.js/r83/three.min.js">script>
        <script src="libs/OrbitControls.js">script>

        <script>

            var scene,camera,renderer,light,controls;//场景,相机,渲染器,光源
            var raycaster,mouse;//光投射器,鼠标位置对应的二维向量

            init();

            function init() {

                var container = document.getElementById("drawArea");

                /*
                    1、初始化渲染器
                */
                renderer = new THREE.WebGLRenderer();
                // renderer.setClearColor('white');//设置渲染出来的背景色
                renderer.setPixelRatio( window.devicePixelRatio );
                renderer.setSize(window.innerWidth,window.innerHeight);
                container.appendChild(renderer.domElement);

                /*
                    2、初始化相机
                        创建相机【远景相机,与人眼观察类似,近大远小】
                        param1:视角【视角越大  物体渲染到屏幕时则看着越小,反之越大】
                        param2:相机拍摄面的长宽比
                        param3:近裁剪面
                        param4:远裁剪面
                */
                camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,2000);
                camera.position.set(10,10,800);

                /*
                    添加视图控制器
                */
                controls = new THREE.OrbitControls( camera, renderer.domElement );
                controls.addEventListener( 'change', render );

                /*
                    3、初始化场景
                */
                scene = new THREE.Scene();
                scene.background = new THREE.Color(0xf0f0f0);


                //initLight();
                //scene.add( new THREE.PointLightHelper( light, 15 ) );

                /*
                    4、添加辅助坐标轴
                */
                var axes = new THREE.AxisHelper(800);  
                scene.add(axes);

                /*
                    5、添加地面网格
                */
                /**
                 * size 网格总边长
                 * step 网格个数
                 * colorCenterLine  网格中心线颜色
                 * colorGrid    网格其他线颜色
                 */
                var gridHelper = new THREE.GridHelper( 300, 10, 'red', 'gray' );
                gridHelper.position.y = -100;
                gridHelper.position.x = 0;
                scene.add( gridHelper );

                /*
                    6、添加正方体
                */
                var geometry = new THREE.BoxGeometry(20,20,20);//盒子模型

                for ( var i = 0; i < 100; i ++ ) {
                    var material = new THREE.MeshBasicMaterial({color:"gray"});//材料
                    var mesh = new THREE.Mesh( geometry, material );
                    mesh.position.x = ( Math.random() - 0.5 ) * 1000;
                    mesh.position.y = ( Math.random() - 0.5 ) * 1000;
                    mesh.position.z = ( Math.random() - 0.5 ) * 1000;
                    scene.add( mesh );
                }


                /*
                    7、添加光投射器 及 鼠标二维向量 用于捕获鼠标移入物体

                        下次渲染时,通过mouse对于的二维向量判断是否经过指定物体
                */
                raycaster = new THREE.Raycaster();//光线投射器
                mouse = new THREE.Vector2();//二维向量 
                document.addEventListener('mousemove', function(){
                    event.preventDefault();
                    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
                    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
                }, false);


                /**
                 * 浏览器窗口大小调整
                 */
                 window.addEventListener( 'resize', function(){

                    camera.aspect = window.innerWidth / window.innerHeight;
                    camera.updateProjectionMatrix();
                    renderer.setSize( window.innerWidth, window.innerHeight );

                }, false );

                /**
                 * 添加鼠标点击事件,捕获点击时当前选中的物体
                 */
                window.addEventListener( 'click', function(){

                    if(projectiveObj){
                        console.log(projectiveObj);
                        if(projectiveObj.hasChecked){
                            projectiveObj.hasChecked = false;
                            projectiveObj.material.color.set("gray");
                        }else{
                            projectiveObj.hasChecked = true;
                            projectiveObj.material.color.set("#dd830d");
                        }
                    }

                }, false );

                render();
            }


            function render() {

                requestAnimationFrame(render);

                renderRaycasterObj(raycaster,scene,camera,mouse);//渲染光投射器投射到的对象

                renderer.render( scene, camera);

            }

            var projectiveObj;//定义上次投射到的对象
            /**
             * 根据光投射器判断鼠标所在向量方向是否穿过物体,穿过则改变物体材质
             * @param {*} raycaster 光投射器
             * @param {*} scene     场景
             * @param {*} camera    相机
             * @param {*} mouse     鼠标位置对应的二维向量
             */
            function renderRaycasterObj(raycaster,scene,camera,mouse) {
                raycaster.setFromCamera(mouse, camera);
                var intersects = raycaster.intersectObjects(scene.children);
                if (intersects.length > 0) {
                    var currentProjectiveObjT = intersects[0].object;
                    if (projectiveObj != currentProjectiveObjT) {

                        if((currentProjectiveObjT instanceof THREE.AxisHelper) || (currentProjectiveObjT instanceof THREE.GridHelper)){
                            //穿过的是坐标轴线和网格线
                            return;
                        }

                        projectiveObj.material.color.setHex(projectiveObj.currentHex);
                        projectiveObj = intersects[0].object;
                    }
                } else {
                    projectiveObj = null;
                }
            }
        script>
    body>
html>

你可能感兴趣的:(javascript)