Three.js camera初探——转场动画实现

news/2024/11/28 9:36:03/

背景

首先简单介绍一下three.jsthree.js是用javascript写的基于webGL的第三方3D库,通过它可以在网页中进行3D建模,结合上TweenMax.js动画库,在网页中实现3D动画效果就变得很简单了。

这是three.js建模的简单流程图例:

用通俗的话来讲,首先可以用js创建各种形状的几何体,或者从外部导入建好的模型文件,然后为几何体添加材质(纹理、颜色等),就组成了一个网格模型mesh,我们可以创建很多的模型,塞进场景容器里,还要为场景加入灯光,通过“打光”照相机才能拍到场景里面的物体,当要拍摄动态场景时,就需要照相机不断的拍摄然后通过渲染器不停地渲染到屏幕上(渲染循环),最后屏幕展现的就是一个3D动态场景。

既然是通过照相机去拍摄场景,让我们在屏幕上可以看到,那么移动照相机用不同的角度拍摄这个世界,自然就可以看到不一样的世界了。

three.js中的camera

three.js中的camera分为两种,一种是正投影相机,一种是透视投影相机,两种的大致区别是:

(图片来自webGL中文网)

在透视投影下,同样大小的物体,在屏幕下远处的物体会比近处的物体小,而正投影下两者是一样大小的。

在本例demo中,我们用的是透视投影,实例化代码如下:

camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);

复制

四个参数分别表示视角,看到的窗口宽度和高度的比例,能看到的最近处的距离,和能看到的最远处的距离。视角越大,拍摄到的场景范围就越大,能看到的物体就显得越小。

接着便是camera位置的设置,在初始化camera时,一般都会先设置好它的3个属性,position/up/lookAt.以demo为例讲解一下这三个属性。在这之前,我们先了解一下three.js的坐标系,使用的是右手坐标系,如下图所示:

就是这么有气质的手势~~大拇指指向x轴正方向,食指指向y轴正方向,中指指向z轴正方向。

再回来看看camera的初始化代码:

camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 500;
camera.up.x = 0;
camera.up.y = 1;
camera.up.z = 0;
camera.lookAt({x : 0 ,y : 0, z : 0});

复制

  1. camera.position: 顾名思义,就是camera在坐标系中的所在位置,处于z轴正方向上离原点500处。
  2. camera.up:比较难理解,指的是camera“头顶”的方向和向量(0,1,0)同向,即和y轴正方向同向。画个图理解一下:

  1. camera.lookAt: 指的就是camera面向哪里,这里是直接面向原点。

另外,camera.up设置的方向必须与camera位置和lookAt的连线不能平行,否则拍不到场景,这个大家自己可以摆摆手势体会一下~

demo实现过程-计算

1.准备过程

在初始化three.js后,创建我们需要的物体,在这里我随机创建了几个正方体,它们的大小和位置都是随机的,面向屏幕的一面加载了一张图片纹理,作为正面,如下图所示:

如果从y轴正方向往y轴负方向看,示意图大致是这样子的(蓝色代表正方体,有粗线加箭头的一面代表正方体有图片的正面,黑色的圆柱体代表照相机,箭头指明拍摄方向):

接下来便是动画过程,需要注意的是,接下来的都是物体只绕y方向旋转,x/z方向只做位移,这样就把一个三维空间的运动转化为二维空间了~~

2.将照相机移到y轴上,旋转正方体和照相机使之正对,如下图所示:

在初始化时,我们便记录了正方体的坐标值(x,y,z),正方体从面向屏幕到面向y轴要旋转多少角度,我这里用了初中数学方法——反三角函数算出。如下图所示分别为四个象限物体需要旋转的角度值。

旋转了正方体后,照相机只要和正方体旋转同样的角度,并坐标中的y值移到和正方体同向,就可以拍摄到正方体正面了。

  1. 因为之前所说的正方体是大小不一的,需要移动照相机使得照相机和正方体的距离与正方体的大小保持一定的比例,这样看到每个正方体的大小才是一致的。所以需要计算照相机的位移,如下图:

我们已知正方体的边长a,假设照相机与正方体中心点的距离设置为3a,利用相似三角形边长等比例的原理得出照相机的该移到的地方(x2,z2)坐标,公式如下:

  1. 为了让正方体具备随机摆放的感觉,还可以让正方体再绕y方向随机转动一定角度,照相机再绕正方体的中心点旋转到正对正方体正面的位置:

计算方法如下:

如上图所示,照相机原来是在正方体中心和原点的连线上的坐标(x,z),绕正方体的中心点(rx,rz)旋转随机角度θ后得到的(x',z')的计算公式如下:

以上的角度计算过程,都可以用js中强大的Math函数搞定,包括Math.atan()\math.cos()等等,具体代码就不贴了。

demo实现过程-动画

上面过程中的第2、3步,直接调用TweenMax.js的动画库,控制camera.position/camera.rotation就可以了。但是第4步由于不能想css一样直接设定transform-origin为正方体中心点,所以必须自己实现。例如控制位移:


TweenMax.to(camera.position,  //指明控制的属性2, //动画时间{x:x2,y: mesh[index].position.y,z:z2,delay:0,ease:Cubic.easeIn} //需要移动的距离
);

复制

这里用到的是requestAnimationFrame()来实现,通过一点点地改变camera的旋转和位置的移动,直到达到角度θ。

var rate;  //旋转频率
function cameraRoAni(){var ani;//当物体的旋转角度大于0if (rotateMesh[index-1] > 0) {rotateRate = rotateRate + rate;if(rotateRate <= rotateMesh[index-1]){var newX = (camera.position.x - mesh[index-1].position.x)*Math.cos(-rate) - (camera.position.z - mesh[index-1].position.z)*Math.sin(-rate) +  mesh[index-1].position.x;var newZ = (camera.position.x - mesh[index-1].position.x)*Math.sin(-rate) + (camera.position.z - mesh[index-1].position.z)*Math.cos(-rate) +  mesh[index-1].position.z;camera.position.x = newX;camera.position.z = newZ;camera.rotation.y += rate;ani = requestAnimationFrame(cameraRoAni);}else{cancelAnimationFrame(ani);}//当物体的旋转角度小于0}else{... //代码和大于0时相似}else{cancelAnimationFrame(ani);}}if (rate>0.01) {rate = rate - 0.0001;}
}

http://www.ppmy.cn/news/241563.html

相关文章

vue解决浏览器中跳转新页面缓存上一页表单等内容方法

在工作中&#xff0c;有可能会遇到需要缓存页面或组件的功能。 情况1&#xff1a;比如在h5中有个一个50个表单&#xff0c;在填到第40个表单时&#xff0c;需要你去另一个新页面去选择列表项&#xff0c;然后把数据带回来。需要我们不仅把数据带回来还要保留前面已经填好的40个…

秒懂汉诺塔

递归经典题&#xff08;汉诺塔&#xff09; 什么是汉诺塔呢&#xff1f;&#xff1f;&#xff1f;   汉诺塔&#xff08;Tower of Hanoi&#xff09;&#xff0c;又称河内塔。源自印度古老传说的一个游戏&#xff0c;大梵天创造世界的时候做了三根金刚石柱子&#xff0c;在一…

SpringBoot整合Mybatis-Plus多数据源

一、前言 随着业务的不断扩展和复杂度的增加&#xff0c;我们在开发过程中往往需要访问多个数据库。 比如&#xff1a; 我们可能需要同时访问主数据库和从数据库&#xff0c;或者访问多个独立的数据库来处理不同的业务逻辑。这时候&#xff0c;我们就需要使用多数据源来实现对…

通过Visual Studio诊断工具定位软件CPU瓶颈

通过VS诊断工具定位软件CPU瓶颈 前情提示&#xff1a;正常情况下我们使用调试模式会看不到诊断工具窗口&#xff0c;控制台会报“无法启动标准收集器。请尝试修复 Visual Studio 的安装。 (HRESULT: 0xe1110002)”这样的错误。 解决方式&#xff1a;通过[Downloads - Visual St…

联想yoga13s锐龙版和酷睿版 哪个好

联想yoga13s两个版本的屏幕都是一样的&#xff0c;都采用了13.3英寸的尺寸大小的屏幕&#xff0c;分辨率都是2.5k&#xff0c;色域为100%sRGB高色域&#xff0c;屏幕占比比较高&#xff0c;为全面屏设计&#xff0c;两个版本的屏幕素质不错&#xff0c;是目前轻薄本市场中第一梯…

联想拯救者y7学计算机可以用吗,2018什么笔记本电脑好 联想拯救者y7000评测

如今&#xff0c;爱好网游的年轻朋友非常多&#xff0c;尤其是热衷于端游的人较多。为了使自己在玩游戏时不出现卡顿的现象&#xff0c;越来越多的朋友都选择购买游戏本。于是&#xff0c;许多电脑品牌纷纷推出游戏本&#xff0c;当然联想也不例外。那么下面小编就来给大家具体…

联想拯救者r720适合java么_联想拯救者哪个型号好 联想拯救者r720怎么样【详解】...

目前&#xff0c;联想这一品牌旗下的笔记本或者电脑在我们生活中出现的频率很高&#xff0c;因为其产品质量一直以来都让广大消费者十分放心。针对一些游戏爱好者&#xff0c;联想推出了一系列的游戏本&#xff0c;拯救者就是其中比较热门的系列。但是&#xff0c;究竟 联想拯救…

学计算机r7000和y7000哪个好,分析看看联想拯救者r7000和y7000区别是什么?哪个好?真相评测揭秘...

这两款联想拯救者r7000和y7000区别不是很大的哈&#xff0c;款式和配置是差不多的&#xff0c;只是说联想拯救者y7000p大气一些的&#xff0c;看个人喜欢吧&#xff0c;我自己用的是联想拯救者y7000p&#xff0c;这款性价比蛮高的&#xff0c;质感蛮强的&#xff0c;电脑贼棒.外…