threejs构建web三维视图入门教程

本文是一篇简单的webGL+threejs构建web三维视图的入门教程,你可以了解到利用threejs创建简单的三维图形,并且控制图形运动。若有不足,欢迎指出。

一、创建场景
我们所见的视图由两个部分共同创建,scene和camera。
首先定义一个场景:
var scene = new THREE.Scene();
然后定义一个相机:
var camera = new THREE.PerspectiveCamera( 90, width/height, 0.1, 1000 );
等等,定义相机需要视窗的长宽。现在我要让我的绘图显示在页面的一个区域(<div>)标签中。我们来选中这个元素,获取它的长宽。
var container = document.getElementById(‘canvasdiv‘);
var width = canvasdiv.clientWidth;
var height = canvasdiv.clientHeight;
这样再加上前面的一行代码,我们就完成了对相机的定义。然后把相机位置设定在z轴上方便观察。
camera.position.set(0,0,10)

现在我们需要一个渲染器把定义好的场景渲染出来。
var renderer = new THREE.WebGLRenderer();
给这个渲染器合适的大小。
renderer.setSize( width, height );
然后将其加入到dom中。
canvasdiv.appendChild( renderer.domElement );
(运行以后发现这其实就是一个canvas元素。其实我们也可以在html中创建canvas元素再将renderer绑定到它上面。var renderer = new THREE.WebGLRenderer({ canvas: document.getElementById(‘mainCanvas‘) });)
最后进行渲染。
renderer.render(scene,camera);
这样,就建立了一个简单的3d场景。

二、绘制图形
我将threejs中的物体理解为模型+材料。以一个长方体为例。
创建模型:
var geometry = new THREE.BoxGeometry( 1,2,1 );
定义材料:
var material = new THREE.MeshBasicMaterial( { color: 0x645d50 } );
有了这两者,我们就可以构建一个长方体方块了。
var cube = new THREE.Mesh( geometry, material );
我们将其添加到场景中显示。
scene.add( cube );
这样,一个三维的长方体就绘制完成了
关于其他形状的绘制,张雯莉的threejs入门指南中介绍的很详细,在此不多赘述。
这部分的完整代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style type="text/css">
#canvasdiv{
    width: 600px;
    height: 600px;
}

    </style>
    <script src="js/three.min.js"></script>
</head>
<body>

    <div class="main-content" id="canvasdiv">

    </div>

<script type="text/javascript" >
var container = document.getElementById(‘canvasdiv‘)
var scene = new THREE.Scene();
var width = canvasdiv.clientWidth;
var height = canvasdiv.clientHeight;
var camera = new THREE.PerspectiveCamera( 90, width/height, 0.1, 1000 );
camera.position.set(0,0,10);
var renderer = new THREE.WebGLRenderer();
renderer.setSize( width, height );
canvasdiv.appendChild( renderer.domElement );
var geometry = new THREE.BoxGeometry( 2,1,1 );
var material = new THREE.MeshBasicMaterial( { color: 0x645d50 } );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
renderer.render(scene,camera);
</script>
</body>
</html>

看上去它只是一个长方形而已,但是它确实是一个立体图形,你可以改变一下camera的位置来观察一下。
camera.position.set( 5,3,10 );


好了,这样看起来是一个立体的长方体了吧。

三、创建3d对象
大多数时候,我们需要讲绘制的图形整合到一起进行控制。此时,我们便需要一个3d对象。
在上面绘制的那个长方体上面再放一个球。
var geometry = new THREE.SphereGeometry( 0.5,100,100 );
var material = new THREE.MeshBasicMaterial( { color: 0xb9c16c } );
var ball = new THREE.Mesh( geometry,material );
ball.position.set( 0,0,1 );
scene.add(ball);
另说一句,默认放置mesh的位置是( 0,0,0 ),和改变相机位置一样,我们可以用ball.position.set方法来改变图形或对象的位置。因此动画也利用这个方法来实现。
然后要把它们整合成一个对象。
首先我们创建一个对象。
var myobj = new THREE.Object3D();
然后把我们画的图形添加到对象里就ok啦。
myobj.add( cube );
myobj.add( ball );
这时候我们已经有了一个3d对象,它包含我们刚刚绘制的长方形和球。于是就没有必要像原来那样把图形一个一个地放置到场景里,只需要把刚刚创建的对象放置到场景里。
scene.add( myobj );

完整代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style type="text/css">
#canvasdiv{
    width: 600px;
    height: 600px;
}

    </style>
    <script src="js/three.min.js"></script>

</head>
<body>

    <div class="main-content" id="canvasdiv">

    </div>

<script type="text/javascript" >
var container = document.getElementById(‘canvasdiv‘)
var scene = new THREE.Scene();
var width = canvasdiv.clientWidth;
var height = canvasdiv.clientHeight;
var camera = new THREE.PerspectiveCamera( 90, width/height, 0.1, 1000 );
camera.position.set( 0,0,10 )
var renderer = new THREE.WebGLRenderer();
renderer.setSize( width, height );
canvasdiv.appendChild( renderer.domElement );

var geometry = new THREE.BoxGeometry( 2,1,1 );
var material = new THREE.MeshBasicMaterial( { color: 0x645d50 } );
var cube = new THREE.Mesh( geometry, material );
//scene.add( cube );

var geometry = new THREE.SphereGeometry( 0.5,100,100 );
var material = new THREE.MeshBasicMaterial( { color: 0xb9c16c } );
var ball = new THREE.Mesh( geometry,material );
ball.position.set( 0,0,1 );
//scene.add(ball);

var myobj = new THREE.Object3D();
myobj.add( cube );
myobj.add( ball );
scene.add( myobj );

renderer.render(scene,camera);
</script>
</body>
</html>

显示效果:

threejs支持从外部导入.obj文件,听说这种文件是用3DsMax绘制的,用PS也可以编辑。我们需要引入OBJMTLLoader.js,MTLLoader.js文件;也有一个OBJLoader.js,但利用这个库只能导入模型而不能导入绘制obj时添加的材质,个人感觉不是非常实用,就不做介绍了。这时候,我们需要把文件们放到一个服务器上,否则会出现跨域问题。
为了让图像更明显,我们添加一些光线。
scene.add( new THREE.AmbientLight( 0xffffff ) );
这里,我们通过导入图片来设置这个对象的纹理。

var texture = new THREE.Texture();
var loader = new THREE.ImageLoader( );
loader.load( ‘tank.jpg‘, function ( image ) {
    texture.image = image;
    texture.needsUpdate = true;
} );

开始导入我们的3D对象!

var loader = new THREE.OBJMTLLoader();
loader.load(‘tank.obj‘,‘tank.mtl‘,function(object){
    tank = object;

    object.traverse(function(child){
        if (child instanceof THREE.Mesh){
        //将贴图赋于材质
            child.material.map = texture;
            child.material.transparent = true;
        }
    });
    object.position.set(0,0,0);
    scene.add( object );
    camera.lookAt( object.position );
    renderer.render( scene,camera );
});  


模型导入进去了,但是看起来还是很奇怪,这就要我们加一些其他光线渲染一下。在这里我们添加平行光线。
var directionalLight = new THREE.DirectionalLight( 0xffffff, 1.5 );
directionalLight.position.set( 1, 1, 1 );
scene.add( directionalLight );


变得光泽多了。

从外部导入obj的完整代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style type="text/css">
#canvasdiv{
    width: 1200px;
    height: 800px;
}

    </style>
    <script src="js/three.min.js"></script>
    <script src="js/MTLLoader.js"></script>
    <script src="js/OBJMTLLoader.js"></script>
</head>
<body>

    <div class="main-content" id="canvasdiv">

    </div>

<script type="text/javascript" >
var container = document.getElementById(‘canvasdiv‘)
var scene = new THREE.Scene();
var width = canvasdiv.clientWidth;
var height = canvasdiv.clientHeight;
var camera = new THREE.PerspectiveCamera( 90, width/height, 0.1, 1000 );
camera.position.set( -10,10,10);
var renderer = new THREE.WebGLRenderer();
renderer.setSize( width, height );
canvasdiv.appendChild( renderer.domElement );

var texture = new THREE.Texture();
var loader = new THREE.ImageLoader(  );
loader.load( ‘tank.jpg‘, function ( image ) {

    texture.image = image;
    texture.needsUpdate = true;

} );
var loader = new THREE.OBJMTLLoader();
loader.load(‘tank.obj‘,‘tank.mtl‘,function(object){
    tank = object;
    object.traverse(function(child){
        if (child instanceof THREE.Mesh){
            //将贴图赋于材质
            child.material.map = texture;
            //重点,没有该句会导致PNG无法正确显示透明效果
            child.material.transparent = true;
        }
    });
    object.position.set(0,0,0);
    scene.add( object );
    camera.lookAt( object.position );
    renderer.render( scene,camera );
});
scene.add( new THREE.AmbientLight( 0xffffff ) );
var directionalLight = new THREE.DirectionalLight( 0xffffff, 1.5 );
directionalLight.position.set( 1, 1, 1 )
scene.add( directionalLight );

renderer.render(scene,camera);
</script>
</body>
</html>

四、动画
现在我们想办法让这些图形动起来。
在threejs中运用最多的动画是用requestAnimationFrame()方法。也可以利用传统的setInterval()做,但用这个会掉帧。
这里我们做一个render函数,来进行渲染和动画调用。这里以前面添加了myobj对象的代码为基础。
现在来不断地改变对象的角度方便对其进行观察。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style type="text/css">
#canvasdiv{
    width: 600px;
    height: 600px;
}

    </style>
    <script src="js/three.min.js"></script>

</head>
<body>

    <div class="main-content" id="canvasdiv">

    </div>

<script type="text/javascript" >
var container,camera,scene,renderer,myobj;

var init = function () {
    container = document.getElementById(‘canvasdiv‘)
    scene = new THREE.Scene();
    var width = canvasdiv.clientWidth;
    var height = canvasdiv.clientHeight;
    camera = new THREE.PerspectiveCamera( 90, width/height, 0.1, 1000 );
    camera.position.set( 0,0,10 )
    renderer = new THREE.WebGLRenderer();
    renderer.setSize( width, height );
    canvasdiv.appendChild( renderer.domElement );

    var geometry = new THREE.BoxGeometry( 2,1,1 );
    var material = new THREE.MeshBasicMaterial( { color: 0x645d50 } );
    var cube = new THREE.Mesh( geometry, material );
    //scene.add( cube );

    var geometry = new THREE.SphereGeometry( 0.5,100,100 );
    var material = new THREE.MeshBasicMaterial( { color: 0xb9c16c } );
    var ball = new THREE.Mesh( geometry,material );
    ball.position.set( 0,0,1 );
    //scene.add(ball);

    myobj = new THREE.Object3D();
    myobj.add( cube );
    myobj.add( ball );
    scene.add( myobj );
}

var render = function () {
    requestAnimationFrame( render );
    myobj.rotation.x+=0.01;
    myobj.rotation.y+=0.01;
    renderer.render(scene,camera);
}
init()
render()
</script>
</body>
</html>

接着让我们对动画进行控制。
在我实现的项目中,是通过websocket连接后台传入参数来控制对象运动的,这里就介绍一下使用参数控制吧。
这里有一个问题,就是requestAnimationFrame回调的函数不能带有参数,否则会出现奇怪的bug。所以我选择用一个全局对象来进行控制。
var control={
s:0,
p:0,
q:0,
j:0,
}
这里s是运动的速度,p,q,j分别是myobj将要运动到的位置的x,y,z坐标。我们先写一个控制它在x轴上运动的函数:

var run = function () {
    if ( myobj.position.x<control.p ) {
        myobj.position.x += control.s;
        requestAnimationFrame( run );
        renderer.render( scene,camera )
    };
    if ( myobj.position.x>control.p ) {
        myobj.position.x -= control.s;
        requestAnimationFrame( run );
        renderer.render( scene,camera )
    };
}

再在render函数中添加对run的调用requestAnimationFrame( run )。这样就可以在命令行中改变对象control的值实现控制myobj的运动。但是在运动停止后我的浏览器为什么会变得很卡,而且运动速度回有变化。我还不知道原因。不知道有没有朋友和我有同样的问题。于是我把函数拆成了两个,这样浏览器性能好些。

var run = function () {

    if ( myobj.position.x<control.p ) {
        myobj.position.x += control.s;
        requestAnimationFrame( run );
    };
        renderer.render( scene,camera )
}
var runx = function () {

    if ( myobj.position.x>control.p ) {
    myobj.position.x -= control.s;
        requestAnimationFrame( runx );
    };
        renderer.render( scene,camera )
}

同样的,也可以写出在y,z轴上运动的函数。

在x轴上运动的完整代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style type="text/css">
#canvasdiv{
    width: 600px;
    height: 600px;
}

    </style>
    <script src="js/three.min.js"></script>

</head>
<body>

    <div class="main-content" id="canvasdiv">

    </div>

<script type="text/javascript" >
var container,camera,scene,renderer,myobj;

var init = function () {
    container = document.getElementById(‘canvasdiv‘)
    scene = new THREE.Scene();
    var width = canvasdiv.clientWidth;
    var height = canvasdiv.clientHeight;
    camera = new THREE.PerspectiveCamera( 90, width/height, 0.1, 1000 );
    camera.position.set( 0,0,10 )
    renderer = new THREE.WebGLRenderer();
    renderer.setSize( width, height );
    canvasdiv.appendChild( renderer.domElement );

    var geometry = new THREE.BoxGeometry( 2,1,1 );
    var material = new THREE.MeshBasicMaterial( { color: 0x645d50 } );
    var cube = new THREE.Mesh( geometry, material );
    //scene.add( cube );

    var geometry = new THREE.SphereGeometry( 0.5,100,100 );
    var material = new THREE.MeshBasicMaterial( { color: 0xb9c16c } );
    var ball = new THREE.Mesh( geometry,material );
    ball.position.set( 0,0,1 );
    //scene.add(ball);

    myobj = new THREE.Object3D();
    myobj.add( cube );
    myobj.add( ball );
    scene.add( myobj );
}

var control={
    s:0,
    p:0,
    q:0,
    j:0,
}

var run = function () {

    if ( myobj.position.x<control.p ) {
        myobj.position.x += control.s;
        requestAnimationFrame( run );
    };
        renderer.render( scene,camera )
}
var runx = function () {

    if ( myobj.position.x>control.p ) {
    myobj.position.x -= control.s;
        requestAnimationFrame( runx );
    };
        renderer.render( scene,camera )
}

var render = function () {
    requestAnimationFrame( run );
    requestAnimationFrame( runx );
    renderer.render(scene,camera);
}

init()
render()
</script>
</body>
</html>

这个入门教程就到这里了,感谢阅读。

时间: 2024-10-24 09:37:35

threejs构建web三维视图入门教程的相关文章

spring mvc构建WEB应用程序入门例子

在使用spring mvc 构建web应用程序之前,需要了解spring mvc 的请求过程是怎样的,然后记录下如何搭建一个超简单的spring mvc例子. 1) spring mvc的请求经历 请求由DispatcherServlet分配给控制器(根据处理器映射),在控制器完成处理后,请求会被发送到一个视图(根据viewController解析逻辑视图) 来呈现输出结果. 整理成下图所示: 2)搭建一个简单的spring mvc例子 ①创建一个maven工程,其中pom中要有spring相关

ASP.NET Web API 2 入门教程

译者:jiankunking 出处:http://blog.csdn.net/jiankunking 源码下载 HTTP不仅提供web页面服务,在构建公开服务和数据api方面,它也是一个强大的平台.HTTP简单.灵活.无处不在.几乎你能想到的所有的平台,都有一个HTTP库,因此HTTP服务可以影响到广泛的客户端,包括浏览器.移动设备,和传统的桌面应用程序. ASP.NET Web API是一个基于.NET框架用于构建Web API的框架.在本教程中,您将使用ASP.NET Web API创建一个

ASP.NET Core 入门教程 2、使用ASP.NET Core MVC框架构建Web应用

原文:ASP.NET Core 入门教程 2.使用ASP.NET Core MVC框架构建Web应用 一.前言 1.本文主要内容 使用dotnet cli创建基于解决方案(sln+csproj)的项目 使用Visual Studio Code开发基于解决方案(sln+csproj)的项目 Visual Studio Code Solution插件( vscode-solution-explorer)基础使用介绍 基于 .NET Core web项目模板构建 ASP.NET Core MVC We

ASP.NET Core 入门教程 1、使用ASP.NET Core 构建第一个Web应用

原文:ASP.NET Core 入门教程 1.使用ASP.NET Core 构建第一个Web应用 一.前言 1.本文主要内容 Visual Studio Code 开发环境配置 使用 ASP.NET Core 构建Web应用 ASP.NET Core Web 应用启动类说明 ASP.NET Core Web 项目结构说明 2.本教程环境信息 软件/环境 说明 操作系统 Windows 10 SDK 2.1.401 ASP.NET Core 2.1.3 IDE Visual Studio Code

Android基础入门教程——7.5.1 WebView(网页视图)基本用法

Android基础入门教程--7.5.1 WebView(网页视图)基本用法 标签(空格分隔): Android基础入门教程 本节引言 本节给大家带来的是Android中的一个用于显示网页的控件:WebView(网页视图),现在Android应用 层开发的方向有两种:客户端开发和HTML5移动端开发!所谓的HTML5端就是:HTML5 + CSS + JS来构建 一个网页版的应用,而这中间的媒介就是这个WebView,而Web和网页端可以通过JS来进行交互,比如, 网页读取手机联系人,调用手机相

ASP.NET Core 入门教程 7、ASP.NET Core MVC 分部视图入门

原文:ASP.NET Core 入门教程 7.ASP.NET Core MVC 分部视图入门 一.前言 1.本教程主要内容 ASP.NET Core MVC (Razor)分部视图简介 ASP.NET Core MVC (Razor)分部视图基础教程 ASP.NET Core MVC (Razor)强类型分部视图教程 2.本教程环境信息 软件/环境 说明 操作系统 Windows 10 SDK 2.1.401 ASP.NET Core 2.1.3 IDE Visual Studio Code 1

ASP.NET Core 入门教程 5、ASP.NET Core MVC 视图传值入门

原文:ASP.NET Core 入门教程 5.ASP.NET Core MVC 视图传值入门 一.前言 1.本教程主要内容 ASP.NET Core MVC 视图引擎(Razor)简介 ASP.NET Core MVC 视图(Razor)ViewData使用示例 ASP.NET Core MVC 视图(Razor)ViewBag使用示例 ASP.NET Core NVC 视图(Razor)强类型传值(ViewModel)页示例 2.本教程环境信息 软件/环境 说明 操作系统 Windows 10

影视动画 Premiere视频教程 AE CS5专业入门教程 绘声绘影X6入门提高 3DS MAX三维动画教程

热门推荐电脑办公计算机基础知识教程 Excel2010基础教程 Word2010基础教程 PPT2010基础教程 五笔打字视频教程 Excel函数应用教程 Excel VBA基础教程 WPS2013表格教程 更多>平面设计PhotoshopCS5教程 CorelDRAW X5视频教程 Photoshop商业修图教程 Illustrator CS6视频教程 更多>室内设计3Dsmax2012教程 效果图实例提高教程 室内设计实战教程 欧式效果图制作实例教程 AutoCAD2014室内设计 Aut

Web压力测试工具 LoadRunner12.x简易入门教程--(一)回放与录制

LoadRunner12.x简易入门教程--(一)回放与录制 今天在这里分享一下LoadRunner12.x版本的入门使用方法,希望对刚接触LoadRunner的童鞋有所帮助. LoadRunner12的组成分为三部分,分别是:Virtual User Generator.Controller.Analysis 首先要介绍的是用Virtual User Generator做一个最简单的录制与回放. 打开软件后,界面如下,通过左上角的菜单,我们来新建一个脚本 由于现在Web项目比较多,这里也就用W