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>
  • 相关阅读:
    io学习
    asp.net文件上传进度条研究
    asp.net页面中的Console.WriteLine结果如何查看
    谨慎跟随初始目的不被关联问题带偏
    android 按钮特效 波纹 Android button effects ripple
    安卓工作室 日志设置
    安卓工作室 文件浏览器 android studio File browser
    一个新的Android Studio 2.3.3可以在稳定的频道中使用。A new Android Studio 2.3.3 is available in the stable channel.
    新巴巴运动网上商城 项目 快速搭建 教程 The new babar sports online mall project quickly builds a tutorial
    码云,git使用 教程-便签
  • 原文地址:https://www.cnblogs.com/lmf-sky/p/12196119.html
Copyright © 2011-2022 走看看