`

three.js内部拖拽例子全详解

 
阅读更多
<!DOCTYPE html>
<html>
    <head>
        <title>three.js webgl - draggable cubes</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <style>
            body {
                font-family: Monospace;
                background-color: #f0f0f0;
                margin: 0px;
                overflow: hidden;
            }
        </style>
    </head>
    <body>
        <script src="script/three.js"></script>
        <script src="script/jquery-1.7.2.min.js"></script>
        <script src="script/libs/tween.min.js"></script>
        <script src="script/controls/TrackballControls.js"></script>
        <!-- <script src="script/renderers/CSS3DRenderer.js"></script> -->
        <script src="script/libs/stats.min.js"></script>
            
            
        <script>
            //container是指页面放置这个webGL的一个层  stats是指
            var container, stats;
            //camera是指场景相机 controls是指控制器,比如一般的鼠标视角控制等  scene是场景,就好像一个大的舞台 
            //projector是可能指屏幕和场景转换工具 renderer是指场景渲染,能把场景呈现到浏览器里
            var camera, controls, scene, projector, renderer;
            //objects是指场景中的实体集合  plane是一个水平面网格,当选中一个物体时,可以通过这个水平面,看到和它在同一平面内的其他物理
            var objects = [], plane;
            //mouse,鼠标所对应的二维向量  offset 是指三维偏移向量 INTERSECTED是指相交的对象 SELECTED选中的对象
            var mouse = new THREE.Vector2(),
            offset = new THREE.Vector3(),
            INTERSECTED, SELECTED;
                
            //初始化整个场景
            init();
            //开始每秒最大60帧的渲染
            animate();
    
            function init() {
                //创建一个放置webGL的层
                container = document.createElement( 'div' );
                //把上面的层放到body里
                document.body.appendChild( container );
                //创建一个透视相机 可视角度70度 浏览器的全屏的宽高 水平视锥 最近1 最远10000 
                camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 );
                //相机的位置z正半轴3000
                camera.position.z = 3000;
                //轨迹球控制 鼠标左击旋转  右击平移 滚轮远近
                controls = new THREE.TrackballControls( camera );
                //旋转速度
                controls.rotateSpeed = 1.0;
                //变焦速度
                controls.zoomSpeed = 1.2;
                //平移速度
                controls.panSpeed = 0.8;
                //是否不变焦
                controls.noZoom = false;
                //是否不平移
                controls.noPan = true;
                //可能是惯性 true没有惯性
                controls.staticMoving = false;
                //动态阻尼系数 就是灵敏度
                controls.dynamicDampingFactor = 0.3;
                    
                //新建一个场景
                scene = new THREE.Scene();
    
                    
                //新建一个环境光 就是正常物体都能照到的光
                var ambientLight = new THREE.AmbientLight( Math.random() *0xffffff );
                //把环境光加到场景中
                scene.add( ambientLight );
                //再新建一个无线远的平行光,就是像太阳光一样的,
                var directionalLight = new THREE.DirectionalLight( Math.random() * 0xffffff );
                //把平行光放在y轴正方向上的无穷远处
                directionalLight.position.set( 0, 1, 0 );
                //把平行光加到场景中
                scene.add( directionalLight );
                //再建一个点光源 颜色 强度 照射距离
                var pointLight = new THREE.PointLight( 0xff0000, 1, 500 );
                //设置点光源的位置
                pointLight.position.set(0,0,-200);
                //把点光源加入到场景中
                scene.add( pointLight );
                //定义一个球体
                var geometry = new THREE.SphereGeometry( 70, 32, 16 );
    
                for ( var i = 0; i < 50; i ++ ) {
                    //把这个球体加上网格材质,随机生成一种颜色的网格对象
                    var object = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } ) );
                        
                    //把材质颜色放到对象的环境颜色上,还没有理解
                    object.material.ambient = object.material.color;
                        
                    //随机放置一个位置
                    object.position.x = Math.random() * 3000 - 1500;
                    object.position.y = Math.random() * 1800 - 1000;
                    object.position.z = Math.random() * 2400 - 1200;
                        
                    //加到场景中去
                    scene.add( object );
                        
                    //放到对象数组中
                    objects.push( object );
    
                }
                //创建一个长2000宽2000,8*8的网格对象并加上一种基本材质
                plane = new THREE.Mesh( new THREE.PlaneGeometry( 2000, 2000, 8, 8 ), new THREE.MeshBasicMaterial( { color: 0x000000, opacity: 0.25, transparent: true, wireframe: true } ) );
                //网格对象是否可见
                plane.visible = true;
                //把网格对象加到场景中
                scene.add( plane );
                    
                //创建一个屏幕和场景转换工具
                projector = new THREE.Projector();
                //创建一个抗锯齿的webgl渲染器
                renderer = new THREE.WebGLRenderer( { antialias: true } );
                //是否排列对象 默认是true
                renderer.sortObjects = false;
                //设置渲染的范围
                renderer.setSize( window.innerWidth, window.innerHeight );
                //是否启用阴影地图
                renderer.shadowMapEnabled = true;
                //设置阴影地图是纹理阴影
                renderer.shadowMapType = THREE.PCFShadowMap;
                //把渲染成的所有页面标签加入到webgl层中
                container.appendChild( renderer.domElement );
                    
                //显示了一个左上角的性能监视窗口
                stats = new Stats();
                stats.domElement.style.position = 'absolute';
                stats.domElement.style.top = '0px';
                container.appendChild( stats.domElement );
                    
                //加入鼠标拖动对象的一系列监听事件
                renderer.domElement.addEventListener( 'mousemove', onDocumentMouseMove, false );
                renderer.domElement.addEventListener( 'mousedown', onDocumentMouseDown, false );
                renderer.domElement.addEventListener( 'mouseup', onDocumentMouseUp, false );
    
                //加入窗口改变大小时的监听事件
                window.addEventListener( 'resize', onWindowResize, false );
    
            }
            //窗口改变大小时的触发事件
            function onWindowResize() {
                //改变相机的aspect属性为当前窗口的宽高
                camera.aspect = window.innerWidth / window.innerHeight;
                //更新相机的投影矩阵
                camera.updateProjectionMatrix();
                //重新设置场景宽高
                renderer.setSize( window.innerWidth, window.innerHeight );
    
            }
                
            //当鼠标移动时触发的事件
            function onDocumentMouseMove( event ) {
                //阻止本来的默认事件,比如浏览器的默认右键事件是弹出浏览器的选项
                event.preventDefault();
                    
                //mouse.x是指 鼠标的x到屏幕y轴的距离与屏幕宽的一半的比值 绝对值不超过1
                //mouse.y是指 鼠标的y到屏幕x轴的距离与屏幕宽的一半的比值 绝对值不超过1
                //
                //下面的矩形是显示器屏幕,三维空间坐标系的布局以及屏幕的二维坐标系
                //
                // 鼠标是从  二维坐标系
                // 这个点 .-------------------------------------------|-->鼠标x正半轴
                //  开始算|                   个 y     /              |
                //   x,y  |                    |     /                |
                //        |                    |   /                  |
                //        |          三维坐标系| /                    |
                //        | -------------------/-------------------->x|
                //        |                  / |                      |
                //        |                /   |                      |
                //        |              /     |                      |
                //        |__________Z_匕______|______________________|
                //        |
                // 鼠标y  \/
                // 正半轴
                mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
                mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
    
                //新建一个三维变换半单位向量 假设z方向就是0.5,这样我左右移的时候,还会有前后移的效果
                var vector = new THREE.Vector3( mouse.x, mouse.y, 0.5 );
                    
                //屏幕和场景转换工具根据照相机,把这个向量从屏幕转化为场景中的向量
                projector.unprojectVector( vector, camera );
                
                //vector.sub( camera.position ).normalize()变换过后的向量vector减去相机的位置向量后标准化
                //新建一条从相机的位置到vector向量的一道光线
                var raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
    
                //是否有东西被选中
                if ( SELECTED ) {
                    //有的话取到这条光线射到的物体所在水平面上所有相交元素的集合,所以这样就可以限制每次拖动距离不能超出水平面panel
                    var intersects = raycaster.intersectObject( plane );
                    //这个鼠标点中的点的位置减去偏移向量,新位置赋值给选中物体
                    if(intersects.length > 0){
                        SELECTED.position.copy( intersects[ 0 ].point.sub( offset ) );
                    }
                    return;
    
                }
    
                //否则的话,光线和所有物体相交,返回相交的物体
                var intersects = raycaster.intersectObjects( objects );
                //如果有物体相交了
                if ( intersects.length > 0 ) {
                    //并且相交物体不是上一个相交物体
                    if ( INTERSECTED != intersects[ 0 ].object ) {
                        //将这个对象放到INTERSECTED中
                        INTERSECTED = intersects[ 0 ].object;
                        //改变水平面的位置
                        plane.position.copy( INTERSECTED.position );
                        //并把水平面指向到相机的方向
                        plane.lookAt( camera.position );
    
                    }
                    //改变鼠标的样式
                    container.style.cursor = 'pointer';
    
                } else {
                    //改变鼠标的样式
                    container.style.cursor = 'auto';
    
                }
    
            }
            //当鼠标按下时触发的事件
            function onDocumentMouseDown( event ) {
                //阻止本来的默认事件,比如浏览器的默认右键事件是弹出浏览器的选项
                event.preventDefault();
    
                var vector = new THREE.Vector3( mouse.x, mouse.y, 0.5 );
                projector.unprojectVector( vector, camera );
    
                var raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
    
                var intersects = raycaster.intersectObjects( objects );
    
                if ( intersects.length > 0 ) {
                    //不能改变视角了
                    controls.enabled = false;
                    //把选中的对象放到全局变量SELECTED中
                    SELECTED = intersects[ 0 ].object;
                    //再和水平面相交
                    var intersects = raycaster.intersectObject( plane );
                        
                    //选中位置和水平面位置(物体中心)的偏移量
                    offset.copy( intersects[ 0 ].point ).sub( plane.position );
                    //改变鼠标的样式
                    container.style.cursor = 'move';
    
                }
    
            }
    
            function onDocumentMouseUp( event ) {
    
                event.preventDefault();
                //又能改变视角了
                controls.enabled = true;
                //如果有相交物体
                if ( INTERSECTED ) {
                    //把位置给水平面
                    plane.position.copy( INTERSECTED.position );
                    //选中物体置空
                    SELECTED = null;
    
                }
                //改变鼠标的样式
                container.style.cursor = 'auto';
    
            }
    
            //每秒最大60帧的渲染,一直在循环
            function animate() {
                //循环本身
                requestAnimationFrame( animate );
                //渲染场景
                render();
                //更新性能监视窗口
                stats.update();
    
            }
    
            function render() {
                //更新控制器
                controls.update();
                //渲染场景和相机
                renderer.render( scene, camera );
            }
        </script>
    </body>
</html>
分享到:
评论

相关推荐

    Three.js源代码例子

    Three.js 是一个非常流行的JavaScript库,专用于在Web浏览器中创建和展示三维图形。这个库是基于 WebGL 技术的,WebGL 是一种允许在浏览器中进行硬件加速的3D图形渲染API。Three.js简化了WebGL的复杂性,使得开发者...

    three.min.js 最全的版本

    总之,"three.min.js"的最全版本是Three.js库的一个完整集合,包含了所有可能需要的功能,让开发者能够充分利用3D技术进行创新。无论是初学者还是经验丰富的开发者,都可以从中找到构建惊艳3D web应用的工具和灵感。...

    three.js拖拽生成场景简单示例

    在这个示例中,`index.html`会引入`threejs.js`和`OrbitControls.js`这两个JavaScript文件。`threejs.js`是three.js的核心库,提供了3D对象、光照、材质等元素的创建和管理功能;而`OrbitControls.js`是three.js的一...

    使用three.js绘制3d图表(柱状图,饼状图,环状图,面积图等).zip

    使用three.js绘制3d图表(柱状图,饼状图,环状图,面积图等).zip使用three.js绘制3d图表(柱状图,饼状图,环状图,面积图等).zip使用three.js绘制3d图表(柱状图,饼状图,环状图,面积图等).zip使用three.js...

    三维模型-three.js-PCD模型文件,用于three.js显示pcd文件

    在三维可视化领域,Three.js是一个非常流行的JavaScript库,它允许开发者在Web浏览器中创建和展示复杂的3D模型。本资源是关于使用Three.js处理PCD(Point Cloud Data)模型文件的,这是一种常见的3D点云数据格式。在...

    Three.js模型包

    Three.js 是一个非常流行的JavaScript库,专用于在Web浏览器中创建和展示三维图形。它利用 WebGL 技术,使得在网页上实现交互式3D视觉效果成为可能,无需用户安装任何插件。这个"Three.js模型包"包含了各种示例使用...

    three.js加载json三维模型.zip

    在三维Web开发领域,Three.js是一个非常流行的JavaScript库,它为浏览器提供了强大的3D图形渲染功能。本主题将深入探讨如何使用Three.js加载JSON格式的三维模型,以及与BIM(建筑信息模型)相关的应用。 一、Three....

    Three.js视频教程源码.rar

    《Three.js全方位解析:从源码到实战》 Three.js是基于WebGL的JavaScript库,是目前最流行的浏览器端3D图形渲染库之一,广泛应用于网页游戏、数据可视化、3D建模等领域。本教程围绕"Three.js视频教程源码.rar"展开...

    blender导出Three.js(.js)插件

    为了确保最佳的性能和兼容性,开发者可能需要密切关注Three.js的更新,适时更新导出工具,或者考虑使用社区维护的更新版本插件,如`blenderio-exporter-threejs`,这是一个更活跃的项目,持续跟进Three.js的最新进展...

    Three.js + Mapbox 实现泛光效果

    Three.js + Mapbox 实现泛光效果 Three.js + Mapbox 实现泛光效果 Three.js + Mapbox 实现泛光效果 Three.js + Mapbox 实现泛光效果 Three.js + Mapbox 实现泛光效果 Three.js + Mapbox 实现泛光效果 Three.js + ...

    three.js跳动的火焰 流动的河

    three.js是JavaScript的一个流行库,用于在Web浏览器中进行3D图形渲染。这个项目可能是为了展示如何利用three.js的特性来模拟真实世界的物理现象,如火的燃烧和水的流动。 在描述中提到的“很简单的一个效果”,...

    three.js开发必备(内附开发指南和three.js多版本)

    《three.js开发必备》资源包含了三个关键组成部分:THREE.JS开发指南的PDF文档和多个版本的three.min.js库。这个资源对于想要深入理解和实践three.js的开发者来说是极其宝贵的。 首先,我们来探讨THREE.JS开发指南...

    基于three.js + canvas实现爱心代码+播放器效果.zip

    基于three.js + canvas实现爱心代码+播放器效果.zip 基于three.js + canvas实现爱心代码+播放器效果.zip 基于three.js + canvas实现爱心代码+播放器效果.zip 基于three.js + canvas实现爱心代码+播放器效果.zip 基于...

    用three.js打造的3D个人炫酷网站.zip

    用three.js打造的3D个人炫酷网站.zip用three.js打造的3D个人炫酷网站.zip用three.js打造的3D个人炫酷网站.zip用three.js打造的3D个人炫酷网站.zip用three.js打造的3D个人炫酷网站.zip用three.js打造的3D个人炫酷网站...

    three. js的人体解剖图.zip

    《Three.js 人体解剖图详解》 Three.js 是一个基于 WebGL 的 JavaScript 库,它为Web开发人员提供了一个在浏览器中创建3D图形的强大工具。这个“three.js的人体解剖图”压缩包,很显然是一个利用Three.js库来展示...

    Three.js-入门指南(带书签).pdf

    Three.js 是一个基于WebGL的JavaScript库,它简化了在网页上使用WebGL创建和显示3D图形的过程。WebGL是一种Web标准,它允许网页使用硬件加速的OpenGL ES图形API,Three.js就是基于这一技术构建,使开发者能够不直接...

    three.js 智慧城市模型

    Three.js 是一款基于 WebGL 的 JavaScript 库,用于在浏览器中创建三维图形和动画,它在构建智慧城市模型中扮演了核心角色。本文将深入探讨如何利用 three.js 来创建智慧城市的虚拟表示,并介绍与之相关的技术知识点...

    Three.js渲染GeoJSON.zip

    在IT领域,Three.js是一个非常流行的JavaScript库,用于在Web浏览器中创建3D图形。它利用WebGL技术,使得开发者可以构建丰富的交互式三维场景。本项目“Three.js渲染GeoJSON”聚焦于如何使用Three.js将地理数据...

    Three.js与arcgis的交互与渲染

    在IT行业中,Three.js是一个非常流行的JavaScript库,用于在Web浏览器中创建3D图形。而ArcGIS则是Esri公司的一款强大的地理信息系统(GIS),用于处理、分析和展示地理数据。当我们谈论“Three.js与ArcGIS的交互与...

    使用three.js 的 交互式 3D 心脏模型

    在本项目中,我们将深入探讨如何使用流行的JavaScript库three.js创建一个交互式的3D心脏模型。three.js是一个强大的WebGL库,它使得在浏览器中构建3D图形变得简单易行。通过结合HTML5 Canvas、SVG和WebGL,three.js...

Global site tag (gtag.js) - Google Analytics