首页 > 其他分享 >three.js实现鼠标拾取例子

three.js实现鼠标拾取例子

时间:2022-09-06 11:11:41浏览次数:54  
标签:鼠标 INTERSECTED 物体 three 拾取 js camera renderer var

image

基本思路

<script>
var renderer,scene,camera;
var light;
var raycaster,//相机->鼠标的射线
	mouse,//鼠标所在位置
	actionObject;//选中的物体
init();
animation();

function init(){
	//渲染器
	//场景
	//相机
	//方向光
	//创建2000个立方体
 
	//创建射线
	//创建鼠标二维向量(圆点到鼠标的向量)
	//鼠标移动事件,目的是进行鼠标归一化操作
}
function animation(){
	render();
	requestAnimation(animation);
}
function render(){
	//相机绕着一个球形旋转
    
	//更新相机与鼠标射线
	//获取与射线相交的物体
	//判断是否有相交的物体
          //有,
              //判断鼠标有没有选中物体。
                    //有,就将之前的物体的颜色恢复回到改变之前的颜色
                    //不管不管之前有没有选中的物体,新的射线相交后有相交的物体都把第一个相交的赋给actionObject,然后保留修改之前的颜色以便后面恢复,最后修改选中物体的颜色

           //没有,
                //判断之前有没有选中过的物体,
                    //有,就恢复之前物体的颜色
                    //不管有没有,都将选中的物体变量设为空
}
</script>

实现代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        body{
            background-color: #f0f0f0;
            margin: 0px;
            overflow: hidden;
        }
    </style>
</head>
<body>
<script src="/js/three.js"></script>
<script src="/js/Stats.js"></script>
<script>
    var renderer,scene,camera;
    var light;
    var raycaster,mouse;
    var stats;
    init();
    animation();

    function init(){

        //性能
        stats = new Stats();
        stats.domElement.style.position = 'absolute';
        stats.domElement.style.top='0px';
        document.body.appendChild(stats.domElement);

        //创建一个渲染器
        renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth,window.innerHeight);
        renderer.setClearColor(0xf0f0f0);
        renderer.setPixelRatio(window.devicePixelRatio);//设置设备像素比。通常用于HiDPI设备防止模糊输出canvas。
        document.body.appendChild(renderer.domElement);
        //创建一个场景
        scene = new THREE.Scene();
        //创建一个相机
        camera = new  THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,1,5000);
        camera.position.x = 50;
        camera.position.y = 50;
        camera.position.z = 500;
        camera.up.x = 0;
        camera.up.y = 1;
        camera.up.z = 0;
        camera.lookAt({
            x:0,
            y:0,
            z:0
        });
        //创建一个方向光
        light = new THREE.DirectionalLight(0xffffff);
        light.position.z = 500;
        scene.add(light);
        //创建2000个立方体
        var geometry = new THREE.BoxGeometry(20,20,20);
        for(var i =0;i<2000;i++){
            var materail = new THREE.MeshLambertMaterial({color:Math.random()*0xffffff});
            var mesh = new THREE.Mesh(geometry,materail);

            mesh.position.x = Math.random()*800-400;
            mesh.position.y = Math.random()*800-400;
            mesh.position.z = Math.random()*800-400;

            mesh.rotation.x = Math.random()*Math.PI*2;//Math.PI*2为圆的周长
            mesh.rotation.y = Math.random()*Math.PI*2;
            mesh.rotation.z = Math.random()*Math.PI*2;

            mesh.scale.x = Math.random()+0.5
            mesh.scale.y = Math.random()+0.5
            mesh.scale.z = Math.random()+0.5

            scene.add(mesh);
        }
        //鼠标拾取
        //创建一个Raycaster光线投射
        raycaster = new THREE.Raycaster();
        //创建一个射线向量
        mouse = new THREE.Vector2();
        //鼠标移动事件,目的是将鼠标坐标归一化
        window.addEventListener('mousemove',onMouseMove,false);

    }
    function animation(){
        stats.begin();
        render();
        stats.end();
        requestAnimationFrame(animation);
        stats.update();
    }

    var radius=100,theta=0;
    var INTERSECTED;
    function render(){
        theta+=0.1;
        camera.position.x = radius*Math.sin(THREE.Math.degToRad(theta));
        camera.position.y = radius*Math.sin(THREE.Math.degToRad(theta));
        camera.position.z = radius*Math.cos(THREE.Math.degToRad(theta));
        camera.lookAt(scene.position);
        camera.updateMatrix();



        //更新鼠标与相机的射线
        raycaster.setFromCamera(mouse,camera);
        //获取与射线相交的所有物体
        var intersects = raycaster.intersectObjects(scene.children);
        //判断是否有相交的物体
            //有,
                //判断鼠标有没有选中物体。
                    //有,就将之前的物体的颜色恢复回到改变之前的颜色
                    //不管不管之前有没有选中的物体,新的射线相交后有相交的物体都把第一个相交的赋给INTERSECTED,然后保留修改之前的颜色以便后面恢复,最后修改选中物体的颜色

            //没有
                //判断之前有没有选中过的物体,
                    //有,就恢复之前物体的颜色
                    //不管有没有,都将选中的物体变量设为空
        if(intersects.length>0){
            if(INTERSECTED) {//如果选中的不是相交的第一个对象,如果INTERSECTED不为空,说明之前有选中过对象,先吧之前的物体回复回原来的颜色,再将新的相交道德第一个物体赋给他
                INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex);//先吧之前的物体回复回原来的颜色
            }
            //不管之前有没有选中的物体,新的射线相交后有相交的物体都把第一个相交的赋给INTERSECTED
            INTERSECTED = intersects[0].object;//将新的相交的第一个物体赋给他
            INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();//保留修改之前的颜色,以便后面恢复
            INTERSECTED.material.emissive.setHex(0xff0000);
        }else{
            if(INTERSECTED) INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex);
            INTERSECTED=null;
        }
        renderer.render(scene,camera);
    }

    function onm ouseMove(event){
        event.preventDefault();
        mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
        mouse.y = -( event.clientY / window.innerHeight ) * 2 + 1;
    }
</script>
</body>
</html>

标签:鼠标,INTERSECTED,物体,three,拾取,js,camera,renderer,var
From: https://www.cnblogs.com/huangchun/p/16661108.html

相关文章

  • 阿卡佩拉 |用 Javascript 制作 |反应 JS
    阿卡佩拉|用Javascript制作|反应JS阿卡佩拉|用Javascript制作|反应JSAcapela可让您控制通知。从一个地方捕获、过滤和操作它们。以两倍的速度解锁您的团队......
  • JS实现点击一个a标签就为其增加一个class,并移除其他同作用的a标签中的class
    html:<ul><li><aclass="list-group-itemtext-center"href="#">中心简介</a></li><li><aclass="list-group-itemtext-center"href="#">师资队伍</......
  • JS实现html列表分页功能
    html代码<divclass="page-block"><divclass="pagepage-1"><ul><liclass="article-hover"><divclass="info-content">......
  • 【面试题】js实现将excel表格copy到页面
    js实现将excel表格copy到页面点击打开视频讲解更加详细其实最核心的技术,还是copy的是我们粘贴板上的数据就像平常怎么粘贴复制其他的数据一样,只是我们在excel粘贴的是一......
  • fastJson将json对象转为java对象,属性名不同的映射(@JSONField)
    JSONObject.toJavaObject(JSONjson,Class<T>clazz);  功能:1.将json转为java对象2.json中下划线格式自动映射到java属性中驼峰格式‘3.如果json中的字段......
  • js for...in和for...of的区别
    jsfor...in和for...of的区别首先,for-in是ES5标准,遍历的是key(可遍历对象、数组或字符串的key);for-of是ES6标准,遍历的是value(可遍历对象、数组或字符串的value)。for...in......
  • 【JS】6. Z 字形变换
    6.Z字形变换二维数组模拟就是找出放单词位置的规律出来varconvert=function(s,numRows){//如果要求的行数都超过了字符串的长度或者本身行数要求就为1......
  • three.js基础用法
    import*asTHREEfrom'../libs/build/three.module.js';import{OrbitControls}from'../libs/jsm/controls/OrbitControls.js'import{CSS2DRenderer,CSS2DObje......
  • js-Promise的all、allSettled、any、race 方法简介
    1、all所有的Promise对象均成功后才会执行all中的then回调,否则返回的是最先rejected状态的值。constpromise1=newPromise((resolve,reject)=>{setTimeout((......
  • 前端js vue的语音播报
    目前h5新增一个文字转语音的功能(但是正在完善中,勉强能用),h5新增的SpeechSynthesisUtterance实例首先new一个SpeechSynthesisUtterance对象使用实例对象的一些属性,包括......