zoukankan      html  css  js  c++  java
  • three.js中的事件

    以上一篇入门篇为例来简单的设置下3d模型当中的交互事件,上一篇我们已经完成了在3d页面中添加了一个红色球,下面我们给这个球一个点击事件让它Y轴位置上升,再设置一个鼠标移入到球上时让其变色。

    1.其实three.js当中没有事件可以直接选中物体的,我们需要监听window对象来完成与3d页面的交互,通过使用到three.js当中RayCaster对象,用于在三维空间中进行鼠标拾取,原理是:相机与鼠标所在的设备坐标之间的连线与哪些物体相交。相交的物体离屏幕越近的越靠前,所以第一个物体就是我们选中的对象。

    第一步:给window对象添加点击事件监听器;

        window.addEventListener('mousedown', mouseDownFuc);
    

    第二步:在事件监听函数里拾取到点击的对象集合;

        function mouseDownFuc(){
            let raycaster = new THREE.Raycaster();//创建光线投射对象
            let mouse = new THREE.Vector2();//创建二维平面
            let intersectsObjArr = getSelsectOBj(mouse,raycaster, e);//通过封装的getSelsectOBj函数获取鼠标选中对象集合,e是点击事件对象
        }     
        //获取事件操作对象
        function getSelsectOBj(mouse,raycaster, e) {
            //将html坐标系转化为webgl坐标系,并确定鼠标点击位置
            mouse.x =  e.clientX / renderer.domElement.clientWidth*2-1;
            mouse.y =  -(e.clientY / renderer.domElement.clientHeight*2)+1;
            raycaster.setFromCamera(mouse,camera);//以camera为z坐标,确定所点击物体的3D空间位置
            let intersects = raycaster.intersectObjects(scene.children, true);//确定所点击位置上的物体数量集合
            return intersects;//返回连线经过的物体集合
        }
    

    第三步:判断intersectsObjArr集合长度不为零,确认我们鼠标点击的地方有物体,如果有物体那么intersectsObjArr[0]就是我们选中的对象,通过页面console.log(intersectsObjArr[0])发现intersectsObjArr[0]包含了相交点的许多信息,而我们只需要交点的对象,所以我们需要取到intersectsObjArr[0].object对象;然后我们还需要进行一次判断当前对象就是我们点击的对象,在这里我们还得回到创建物体时给它的name属性一个值进行区分物体。最后给它position属性值的Y轴坐标设为50;

            myBall.name = 'redBall';//创建物体时给它name属性一个名称
            if(intersectsObjArr.length > 0){
                if(intersectsObjArr[0].object.name == 'redBall'){
                    intersectsObjArr[0].object.position.y = 50;
                }
            }
    

    以上就是我们完成了3d页面物体点击事件,然后就是鼠标的移入到物体变色,移出时颜色还原,这和2d页面的移入移出不太一样,因为我们是给window对象加的监听器,然后通过RayCaster对象来拾取到物体的,所以我们这里需要给window对象加鼠标移动事件来判断鼠标是否移动我们的物体上。其步骤同上点击事件一样。

        window.addEventListener('mousemove', mouseMoveFuc);
        function mouseMoveFuc(){
            let raycaster = new THREE.Raycaster();//创建光线投射对象
            let mouse = new THREE.Vector2();//创建二维平面
            let intersectsObjArr = getSelsectOBj(mouse,raycaster, e);//通过封装的getSelsectOBj函数获取鼠标选中对象集合,e是点击事件对象
            if(intersectsObjArr.length > 0){
                if(intersectsObjArr[0].object.name == 'redBall'){
                    intersectsObjArr[0].object.material = new THREE.MeshPhongMaterial( { color: 'orange'});//移到物体上时颜色变成橘色
                    document.getElementsByTagName('body')[0].style.cursor = 'pointer';//移到物体上时鼠标显示为手
    
                }
            }else{
                    myBall.material =  new THREE.MeshPhongMaterial( { color: 0xff0000});//移出物体时颜色变成原来的红色
                    document.getElementsByTagName('body')[0].style.cursor = 'default';//移出物体时鼠标显示为默认
            }
        }
    

    贴上最终代码:运行一下,看下效果

        <!DOCTYPE html>
        <html>
        <head>
            <meta charset=utf-8>
            <title>event</title>
            <style>
                body {
                    margin: 0;
                    padding: 0;
                    height: 100vh;
                     100vw;
                    overflow: hidden;
                    background: url('img/bgImg.jpg') no-repeat fixed;
                    background-size: 100% 100%;
                }
            </style>
        </head>
        <body>
        <script src="lib/three.min.js"></script>
        <script src="lib/OrbitControls.js"></script>
        <script>
            window.onload = function(){
                let scene,camera,renderer,myBall;
                initThreeScene();
                //物体的事件交互
                window.addEventListener('mousedown', mouseDownFuc);
                window.addEventListener('mousemove', mouseMoveFuc);
                function mouseDownFuc (e) {
                    let raycaster = new THREE.Raycaster();//光线投射,用于确定鼠标点击位置
    	    let mouse = new THREE.Vector2();//创建二维平面
    	    let intersects = getSelsectOBj(mouse,raycaster, e);
                    if(intersects.length > 0) {
                        console.log(intersects[0])
                        if(intersects[0].object.name == 'myBall') {
                            myBall.position.y = 50;
                       }
                    }
                }
                function mouseMoveFuc (e) {
                    let raycaster = new THREE.Raycaster();//光线投射,用于确定鼠标点击位置
    	    let mouse = new THREE.Vector2();//创建二维平面
    	    let intersects = getSelsectOBj(mouse,raycaster, e);
                    if(intersects.length > 0) {
                       if(intersects[0].object.name == 'myBall') {
                           myBall.material =  new THREE.MeshPhongMaterial( { color: 'orange'});
                           document.getElementsByTagName('body')[0].style.cursor = 'pointer';
                       }
                    }else {
                       myBall.material =  new THREE.MeshPhongMaterial( { color: 0xff0000});
                       document.getElementsByTagName('body')[0].style.cursor = 'default';
                    }
                }
                //获取事件操作对象
                function getSelsectOBj(mouse,raycaster, e) {
                    //将html坐标系转化为webgl坐标系,并确定鼠标点击位置
                    mouse.x =  e.clientX / renderer.domElement.clientWidth*2-1;
                    mouse.y =  -(e.clientY / renderer.domElement.clientHeight*2)+1;
                    //以camera为z坐标,确定所点击物体的3D空间位置
                    raycaster.setFromCamera(mouse,camera);
                    //确定所点击位置上的物体数量
                    let intersects = raycaster.intersectObjects(scene.children, true);
                    return intersects;
                }
                function initThreeScene() {
                    scene = new THREE.Scene();
                    camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 2000 );
                    camera.position.set( 0, 50,300 );   
                    renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });//antialias: true;让渲染的平面是光滑的,alpha: true;让渲染的3d背景透明。
                    renderer.setSize( window.innerWidth, window.innerHeight );
                    document.body.appendChild(renderer.domElement );
                    // 给场景添加一个环境光
                    let ambientLight = new THREE.AmbientLight( 0xf5f5f5);
                    scene.add( ambientLight );
                    //辅助线
                    let grid = new THREE.GridHelper( 400, 30, 0xcccccc, 0xcccccc );
                    scene.add( grid );
                    //创建的球
                    let ball = new THREE.SphereGeometry( 25, 100, 100 );//25:球半径 第一个100:水平分割面的数量. 第二个100:垂直分割面的数量.
                    let ballColor = new THREE.MeshPhongMaterial( { color: 0xff0000 } );
                    myBall = new THREE.Mesh( ball , ballColor );
                    myBall.name = 'myBall';
                    scene.add( myBall );
                    let controls =new THREE.OrbitControls(camera, renderer.domElement);
                    controls.enableZoom =true;//允许缩放
                    //设置相机移动距离
                    controls.minDistance = 1;
                    controls.maxDistance = 2000;
                    controls.enableRotate =true;
                    function render() { 
                        requestAnimationFrame( render );
                        renderer.render( scene, camera );
                    } 
                    render();
                    window.onresize = function () {
                        camera.aspect = window.innerWidth / window.innerHeight;//相机重置可视范围
                        camera.updateProjectionMatrix();
                        renderer.setSize( window.innerWidth, window.innerHeight );//渲染器重新渲染可视范围
                    }
                }
            }
        </script>
        </body>
        </html>
  • 相关阅读:
    Git库搭建好之后,当要提交一个新的文件,需要做的是3个步骤
    实习生面试经历
    Word2007中插入公式之后,公式上下有很大的空白
    参考文献规范格式
    Git学习笔记四--远程仓库
    Git学习笔记三--管理修改、撤销修改、删除文件
    Git学习笔记二--工作区和暂存区
    Git学习笔记一--创建版本库、添加文件、提交文件等
    Errors running builder 'DeploymentBuilder' on project '工程名'
    java中运算符与表达式
  • 原文地址:https://www.cnblogs.com/lmf-sky/p/12196119.html
Copyright © 2011-2022 走看看