当前位置: 首页 > Web前端 > HTML

css3d-engine源码学习简析

时间:2023-04-02 23:28:29 HTML

从这里开始准备webgl(准备挖新坑),当然Flutter框架会继续补充,不过我今天学习的不是webgl,而是css3d-engine的库,因为之前做Activity看到一个全景旋转Activity就是用这个库完成的,相当神奇(一开始以为是webgl实现的,后来看了代码才知道原来是可以用CSS3完成,虽然我觉得用webgl应该更合适),抱着好奇心,学了一下。嗯,这个图书馆的设计相当精简。整个库的代码只有800多行,代码压力不大。今天就举个例子来分析一下。对于全景旋转,首先要学习基本坐标系:记住x、y、z轴各自的方向即可,后面的分析会用到。接下来是今天分析的例子,也是来自css3d-engine的例子:一个不停旋转的全景图。当然,我们把镜头拉远一点,发现它其实是一个不停旋转的圆柱体:只不过我们的镜头恰好在圆柱体的内部,所以可以看到全景在不停地旋转。然后分析构建整个场景的代码:vars=newC3D.Stage();s.size(window.innerWidth,window.innerHeight).material({color:"#cccccc"}).update();这里将初始化整个舞台,并创建默认相机:initialize:function(params){...this.el.style[prefix+'Perspective']='800px';this.el.style[prefix+'TransformStyle']='flat';this.el.style[prefix+'Transform']='';this.el.style.overflow='隐藏';this.__rfix=newC3D.Sprite();this.el.appendChild(this.__rfix.el);this.__pfix=newC3D.Sprite();this.__rfix.el.appendChild(this.__pfix.el);this.setCamera(newC3D.Camera());}舞台初始化,默认视角设置为800px,会创建两个Sprites辅助场景搭建(这两个Sprites挺好用的,场景旋转,放大和缩小都是靠这两个Sprite),最后设置camera;when调用update方法,再调用Stage的updateT方法:updateT:function(){this.fov=fixed0(0.5/Math.tan((this.camera.fov*0.5)/180*Math.PI)*这个高度);this.el.style[prefix+'Perspective']=this.fov+'px';这个.__rfix.position(固定0(这个。宽度/2),fixed0(this.height/2),this.fov).rotation(-this.camera.rotationX,-this.camera.rotationY,-this.camera.rotationZ).updateT();this.__pfix.position(-this.camera.x,-this.camera.y,-this.camera.z).updateT();归还这个;},这里可以算是整个Stage计算的核心,首先是Stage的fov计算,它依赖于Camera的fov,Camera的fov默认是75(因为有效视角一个人的角度是75度),然后整个计算其实就是一个已知的角度和对边求邻边的公式:这里的计算方法其实是来自Three.js,github上的讨论可以追溯到什么时候刚才初始化了stage,一开始一口气创建了三个嵌套的div:

我们在舞台设置了perspective属性,在我的电脑上(全屏)计算出来的值为619px,根据刚才的公式,与你浏览器的高度,然后设置__rfix元素位置:屏幕居中,重点在Z轴位置的设置上。可以看到新计算出来的透视等于translateZ(619px),所以当前位置(记住一开始的坐标系是正向屏幕外侧,离视点很近):然后设置的位置__pfix,在Z轴的方向,取相机的反方向,因为我们一般理解的相机是放大缩小。是动的,但是把整个场景往相反的方向移动其实也可以达到同样的效果,所以这里是整个场景移动的方式:现在看,在刚才的代码中,可以看到当x,y,和相机的z更新,其实就是通过移动__pfix来完成的;当相机的rotateX、rotateY、rotateZ更新时,是通过旋转__rfix来完成的。为什么这样设置,我们刚刚看到__rfix将tranlateZ设置为视点,其实目的是让后面的元素可以以视点为原点进行布局,这样我们就可以通过控制来控制用户的视野布局时与视点的距离;旋转时,也可以以视点为原点进行旋转,x、y、z的移动也是以视点为原点进行的。你可以想象这样一个场景,相机缩小200px,然后沿x轴旋转45度。基础舞台的搭建已经明白了,如何继续进行全景旋转:首先,整个场景由20张129*1170的图片组成一个圆柱体,那么这个圆柱体的半径是多少?通过如下计算:0.5*129/Math.tan(360/20/2/180*Math.PI)得到407px,所以代码中把整个场景放在-400px也应该是根据这个半径:varpano=this.createPano(bgData,panoRect);pano.position(0,0,-400).updateT();所以现在整个场景是这样的(可能椭圆更合适):综上所述,这个库还是一个很好的库,也学到了一些3D相关的知识,可以考虑如何融入到日常活动中或者页面以增加吸引力。