react vr 原理解析

react vr中文网:www.vr-react.com

react vr qq群:481244084

示例源码 github:https://github.com/LiuC520/ReactVR/

开发者头条:react vr 原理解析

开发者头条:React VR 视频源码解析

开发者头条:react vr 消息传递原理解析

今天就react vr的原理讲解下: 主要内容有:react vr的加载始末、通信原理、组件的加载等等。建议大家结合本文章对比源码进行翻阅,希望能帮助您了解react vr的原理。

一段话来概括react vr:

一个html两个js文件;

index.bundle.js就是index.vr.js打包的东西,也就是react vr的业务代码、react的代码;

client.js就是新建了一个VRInstace实例,把上面的业务代码传给这个实例:

    包含了根组件的创建、player(相当于Threejs的renderer)渲染、guisys(相当于threejs的scene,管理UI和字体的容器)

    而根组件的创建又包含RN桥的创建(blob)、ReactNativeContext(RN上下文)的创建、原生模块的注册等;

  而RN上下文里面包含一些模块的注册;监听guisys和UIView事件,还有一个搬运工(WebWorker),搬运工会收发传递消息;最后还要调用UI管理器(管理布局UI)

React 和原生js的通信主要就靠这个搬运工了。

后面再详细讲解搬运工和blob的用法,到底这玩意儿是怎么实现的额!

先来看下图,图太大了,我放到网站上可以下载的哦,http://www.vr-react.com/images/react_vr_principle.png,

react vr原理解析图

大纲:

1、react vr基础在html上

2、VRInstance

3、rootView 根组件

4、player(相当于Threejs的renderer)

5、guisys(相当于Threejs的scene)

6、ReactNativeContext(RN上下文对象)

7、UIManager(UI视图管理器)

一、react vr是放在网站上的,首页是html页面


页面下面有三个主要的东东,一个是vr挂载的标签,可以使div、body等等,也就是把vr当成一个标签放到html中;

另一个是client.js文件,这个主要包含的是原生(threejs)的东东;

最后一个是调用原生的初始化函数(init),然后把react vr打包的东东传递给client.js的初始化函数init中。

具体详见下图:


二、VRInstance


这个在client.js中,主要有三个东东在这个文件中,一个是VRInstace的实例,一个是实例的render方法,一个是实例start方法,

2.1、传给VRInstace这个实例几个参数

bundle:也就是react vr那边打包的js文件,也就是你的业务部分了;

字符串:这个是React VR这边注册的根组件,也就是在index.vr.js中注册的根组件名称;

parent:这个是vr要挂载的html的dom节点,可以使html中的某个特定id的div,也可以是放在body上,默认新建的文件都是放在body上的;

options:这个是一个对象,对象里面放的东西有下面18个成员,这些成员可以是html传过来的,也可以是在client.js中新增的,下面我就分别一一介绍着18个东西:

可以把这18个可选参数分成三块,后面也主要分这三块来讲解:

    一块是rootview里面用的,这是rootview是react vr的业务部分,也就是我们自己的打包的业务代码

    一块是player里面用的,相当于three.js中的renderer,这个是ovrui里面的东东,主要是构建three.js的renderer,然后挂在到html的dom节点上,同时也包含了相机,如果你没有设置相机,也没有设置dome节点,这个player会默认创建一个透视相机,同时也会使用默认的body节点;

    一块是GuiSys里面用的,这就相当于是three.js中的scene,也就是一个管理vr物体和模型的容器

下面的18个参数也就是传递给这三块东东的,这些参数讲完,最后也主要是讲解这3块的原理。

2.1.1、传递给rootview的参数:

    customViews:这个是一个数组,包含自定义的view,具体可以看http://www.vr-react.com/NativeMoudles.html

    nativeModules:这是一个数组,包含自定义的原生模块,具体可以看http://www.vr-react.com/NativeMoudles.html

    initialProps:根组件的初始属性,也就是在index.vr.js中注册的那个组件的属性;

    enableHotReload:这个是在调试的时间是否支持热加载的,为true就是支持,false不支持

    assetRoot:这个是资源的根目录,默认是在static_assets下面的,如果是调试模式就是在'../static_assets/'下面,如果是线上的,一般把static_assets文件直接放到html同级的目录下,默认就是static_assets这个目录,当然你可以自己修改啦,改成自己的名字

2.1.2、传递给player的参数:

    pixelRatio:这个是设备的分辨率,如果没有设置,就是window.devicePixelRatio,或者是1

    hideCompass:这个就是一个div节点,就是vr右边中间的显示上下左右的一个图标,默认是没有的,没有的话就给div加个’inline-block‘属性显示出来,如果为true的话,就不显示了;

也就是下面绿色箭头指示的东东:


    camera:这个就是相机,可以自己创建相机,但是只能创建一个相机,没有的话,就会在player中自动创建一个透视相机

    disableTouchPanning:这个是在手机上,禁止手指滑动屏幕旋转相机的,默认是false

    width:renderer的宽度,也就是整个vr渲染的宽度

    height:renderer的高度,也就是整个vr渲染的高度

    allowCarmelDeeplink:允许Carmel浏览器deeplink的,简单的来说,如果为true就是三星,值就是isSamsung,就禁用VR 按钮;

    hideFullscreen:如果为true,就不显示右下角的进入VR的按钮;

    antialias:抗锯齿,默认为true;

    canvasAlpha:这个是WebGLRenderer的不透明度,如果有这个属性,就取antialias的值,如没有默认是true;

    calculateVerticalFOV:这是一个方法,用于自定义宽高计算视角fov的方法;没有这个自定义方法,如果设备是手机,视角就是

fov=Math.max(30,Math.min(70,60/(width/height)));

如果不是手机,视角就固定为60;

2.1.3、传递给GuiSys的参数:

    cursorVisibility:取值取这三个:'visible'|'hidden'|'auto',也就是鼠标或者视线指定到物体上,是否会显示指针的;

    raycasters:这是一个数组,包含射线发射器,如果不存在,就新创建一个MouseRayCaster,如果有,默认选择第一个

    font:设置字体的,没有设置,会默认添加已经有的英文字体,中文字体的使用详见:http://www.jianshu.com/p/1b200198ab41

    scene:three.js的场景,可以把其他的three.js模型添加到这个场景中;

2.2、从client.js调用了另外两个方法,一个是render,一个是start

render如果存在就会传到render里面一个时间戳,会跟着其他的子系统一起刷新,start方法是开启循环,然后调用player(也就是Threejs的renderer)的每一帧运行。

每一帧里面调用的方法如下:

    2.2.1、从client.js传过来的render方法;

    2.2.2、调用player的frame()方法;

    2.2.3、更新GuiSys的东东,相当于Threejs的scene,调用GuiSys的frame方法,把相机和player的renderer方法传过去;

    2.2.4、更新RN这边的东东,调用rootView的frame方法,同时把camera作为参数传过去;

    2.2.5、调用guiSys.getOffscreenRenders,然后调用player.renderOffscreen的方法渲染到外设上,最后调用player的render方法渲染

    2.2.6、最后调用player的requestAnimationFrame来渲染每一帧。

下面就逐个讲解player、guisys、rootview:

三、rootview(上下文对象、上下文的frame方法)

总共有三个参数:传到createRootView上,一个是this.guiSys,一个是root(就是index.vr.js的根组件),最后一个是对象,这个对象除了上面讲的customViews、customViews、initialProps、enableHotReload、assetRoot这几个options传过来的东东,还有bundle、isLowLatency(如果是手机,返回false,否则返回true);


3.1、这里先用RN桥生成一个Blob对象,这个对象的内容就是onmessage,对获取到的内容进行解析;

3.2、然后实例化ReactNativeContext,传过去的参数有三个,一个是guisys,一个是blob的url(类似这样的:blob:http://localhost:8081/92eaa205-dea8-4bb5-bc8a-3e7956ff3a52),一个是options;

3.3、然后看有没有原生组件nativeModules,有的话就用rn注册模块

3.4、然后调用ReactNativeContext的初始化,把bundle的url传过去

3.5、最后返回一个对象,这个对象就是VRInstace里面的rootView,对象有两个成员,一个是ReactNativeContext的实例化,一个是frame函数,调用的就是ReactNativeContext的frame方法,同时把camera和roottag传到frame里面去;

从这里要讲到ReactNativeContext了,这个上下文对象主要是和react bundle进行沟通的,往react来回传递消息的;同时就是异步的工作在文本worker里面,这样主线程UI和浏览器的渲染线程就不会因为工作在react内部而被打断,后面再专门讲解这个东东了哦!

四、player

这个是Ovrui里面的东西啦,简单理解就是facebook把threejs的render,就是WebGLRenderer这个了,把camera和scene挂到dom节点上渲染出来的;

深入点儿就是在dom节点上新建一个div,然后挂上两个东西,一个是overlay,一个是renderer

上面讲了传递给player的几个option里面的参数:

player,后面还有,具体请下载原图慢慢看哦

antialias:抗锯齿;

calculateVerticalFOV:计算视角的自定义函数;

camera:相机;

width:整个vr渲染的宽度;

height:整个vr渲染的高度;

allowCarmelDeeplink:允许Carmel浏览器deeplink的;

disableTouchPanning:禁止在手机滑动移动相机;

pixelRatio:设备像素比;

hideFullscreen:隐藏右下角的vr全屏按钮;

hideCompass:隐藏右侧中间显示方向的指南针;

canvasAlpha:这个是WebGLRenderer的不透明度,如果有这个属性,就取antialias的值,如没有默认是true

除了上面11个参数外,还有下面的3个参数:

elementOrId:这是父节点,vr挂载的dom节点,也就是html标签;默认是body;

onEnterVR:进入VR的回调函数,这个是调用上下面的callFunction方法,发送进入VR的通知;

onExitVR:退出VR的回调函数,这个是调用上下面的callFunction方法,发送退出VR的通知;

下面就讲下这个player是怎么来的:

如何进入player里面的呢?

实例化VRInstace以后,调用了player的frame方法,就是调用控制器的frame方法,最终都是更新相机的位置和旋转的四元数,最后刷新相机的投影矩阵;

首先看这个文件的构成:

4.1、_createClass这是定义函数的构造方法

4.2、首先是引用几个文件:

_AppControls:这是控制部分,基于不同的设备平台来选择不同的控制,在手机上用设备的方向也就是利用陀螺仪,在PC上用指针也就是鼠标;

_OculusPlayer:这个就是一个与支持“ovrweb”协议的VR播放器交互的实用工具,通过`ovrweb:`协议打开一个链接的,返回的是Promise,但是要判断是Edge、火狐、谷歌浏览器。如果Edge浏览器,直接打开就行了,成功就返回,失败就拒绝;如果是火狐浏览器就用iframe打开,如果是谷歌浏览器,移到window上,然后监听blur,监听visibilitychange,然后在监听里面移除监听,没搞懂这个是干嘛的,其他的浏览器直接拒绝

_Overlay:WebVR Player的重叠控件,包含了一个360度的指示器,一个在VR中显示的按钮,Overlay的功能完全由Player控制,它是一个没有真正内在逻辑的布局组件。

_ThreeShim:这个就是把Threejs变成window全局的,在任何地方都可以调用;

_setStyles:把样式设置到dom节点上,根据不同的浏览器添加不同的前缀

_VREffect:给定一个vrDisplay对象,根据当前的眼睛参数配置渲染缓冲区,考虑到适合降低眼睛缓冲区大小以降低帧率的比例因子

4.3、然后 判断是不是手机、android、三星、VR浏览器、支不支持webgl、手机的垂直还是水平方向

4.4、主要还是Player,里面其实就两个东西,一个Player、一个_createClass,总的来说,Player有以下几个成员和方法:

4.4.1、attemptEnterVR:判断是不是VR浏览器就调用enterVR方法,如果不是,调用overlay的disableVRButton禁用按钮方法,然后判断浏览器,如果支持并成功打开VR,就显示VR按钮,如果不支持VR,同样显示VR按钮和支持的信息;

4.4.2、enterVR:通过VR effect请求显示VR,发送进入VR通知,同时设置overlay的VR按钮字体和按键的exitVR事件

4.4.3、exitVR:调用effect的退出展示事件,成功退出的事件中发送退出VR通知、设置VR按钮字体设置VR按键的attemptEnterVR事件

4.4.4、attemptEnterFullscreen:监听不同浏览器的全屏事件,然后在监听事件中调用resize方法

4.4.5、resize:如果render(WebGLRenderer)和相机都存在,设置_wrapper宽高,这个_wrapper就是一个div包含了两个东西,一个是overlay的dom元素,一个是renderer的dom元素。

然后设置render的像素比、setSize;最后设置相机的的视角、相机的视口比例aspect、更新相机的投影矩阵

4.4.6、resetAngles:重新设置相机的角度到初始的位置,也就是调用controls的resetRotation方法设置xyz

4.4.7、frame方法:这是最主要的方法了,VRInstace就是调用这个方法的,下面详细讲解下这个方法:

首先判断浏览器有没有VRFrameData,有的话就实例化这个VRFrameData,然后判断是不是VR显示设备,设备有没有准备好,如果准备好了,就调用获取帧数据方法;

同时把帧数据传递给控制器(controls)的frame方法(其实就是控制的frame其实就是更新相机的位置和方向);

最后更新相机的投影矩阵(updateMatrixWorld),也就是强制更新相机本地变换(camera.matrix)和重新计算全局变换(camera.matrixWorld),因为控制器controls可能会更新相机位置/旋转,并且guiSys需要新的命中测试(hit-testing)值。

4.4.8、renderOffscreen:这个方法也是VRInstace调用的

首先调用_renderUpdate,调用scene的onUpdate更新相机和场景,如果scene内部有子组件如模型啊,相机啊,其他的东东再重复调用_renderUpdate进行渲染;

然后设置render的颜色、sortObjects,再调用renderer的render方法,把场景、相机、渲染的目标传过去进行渲染;

4.4.9、render:这个方法也是VRInstace调用的;

和renderOffscreen一样,同样也是先调用_renderUpdate更新scene及其内部成员;

如果有帧数据而且是VR浏览器,还要调用effect的render方法进行渲染,如果不是手机还要调用_renderMonoCamera;

如果不是VR浏览器直接调用_renderMonoCamera,这个方法的作用是用来准备渲染单眼视图的资源,这里的单眼假设为左眼;原理是先把场景的背景保存起来,如果场景的左侧背景存在,就把场景的背景设置成左侧背景,然后调用render的render方法渲染,最后再把场景的背景设置成最初的状态;

4.4.10、requestAnimationFrame:这个方法也是VRInstace调用的;

这个方法是调用player的每一帧动作,如果是VR显示设备的每一帧方法,如果不是就调用window的每一帧方法进行动画控制。

五、guisys

这个也是Ovrui里面的东西啦;

这是一个在Object3D guiRoot下的UI场景的容器和管理器,管理交互并将事件分发给任何监听器,这个东西其实就跟Threejs的Scene类似,只不过这里面是新建了一个Object3D,其他的东西都加载到这个容器下面,然后把这个容器再放到scene里面。

同样guisys也管理字体,也支持加载多个字体,中文字体的使用详见:http://www.jianshu.com/p/1b200198ab41

由上到下的讲解这个文件的内容:

5.1、首先是一些内部方法

    5.1.1、首先创建一个射线raycaster,以避免每帧都会重建;

    5.1.2、matrixDistance计算两点之间的距离;

    5.1.3、_applyUpdates(node,currentOpacity,updateContext,index,clipRect):

对节点也就是内部成员进行排序的

    5.1.4、updateBillboard

    5.1.5、intersectObject

5.2、创建一个guiRoot,然后加到scene上

方法如下:

5.2.1、add:添加子成员的,如:scene.add(model);

5.2.2、remove:移除成员;

5.2.3、requestFrameFunction:frameUpdateUID自增,同时添加_requestFrames[uid]

5.2.4、cancelFrameFunction:删除_requestFrames[uid]

5.2.5、applyUpdates:把不透明度的应用到分层更新并确定渲染顺序,同时刷新所有的view的位置

5.2.6、frameRenderUpdates:相机放到场景中排序刷新,如果射线存在,调用每一个射线的frame方法;

如果cursorVisibility可见并且没有cursorMesh,就添加cursor;

5.2.7、addCursor:通过makeDefaultCursor方法创建一个默认的cursor,然后cursor的raycast禁用cursor mesh的交互;

探后添加这个mesh到scene中,并且设置为不可见,然后改变渲染顺序为1,也就是在scene之后,scene的顺序为0,让cursor出现在其他物体之上,这样的话一旦检测到和这个射线相交就视为碰撞啦;

5.2.8、makeDefaultCursor:创建canvas,然后画一个默认的cursor;

5.2.9、frame:依次调用三个方法:frameRenderUpdates、frameInputEvents、updateCursor

5.2.10、frameInputEvents:刷新输入事件

设置射线的原点和方向,默认取得是相机的原点和方向;

然后拿到相机的世界坐标,设置raycaster,最后设置cursor的坐标原点等参数;

5.2.11、_fireInputEvents:把目标设置给四种输入源(键盘输入、鼠标输入、触摸输入、手柄输入),然后拿到输入源的getEvents放到数组里面,然后给每一个输入源调用THreejs的事件分发器,分发输入事件

5.2.12、_updateMouseCursorStyle:设置光标的样式

5.2.13、updateCursor:光标放置在与摄像机固定的距离处,除非光标cursorAutoDepth被启用,而且光标位于UI对象上,然后将光标放在与该对象相同的距离处(即intersectDistance)。

5.2.14、_onTouchImmediate:监听回调光标的最后一个碰撞交互的监听

5.2.15、registerOffscreenRender:把场景、相机、渲染的目标放到一个对象(_offscreenRenders)里面,返回一个唯一唯一标识

5.2.16、unregisterOffscreenRender:删除某个特定表示的_offscreenRenders的成员

5.2.17、getOffscreenRenders:获取所有的_offscreenRenders的对象

5.2.18、setFont:设置字体

5.2.19、setMouseCursorInactiveStyle:自定义鼠标光标没有激活的样式

5.2.20、setMouseCursorActiveStyle:设置鼠标光标激活的样式

5.2.21、setCursorVisibility:设置光标的可见与否

5.2.22、setCursorAutoDepth:自动深度的光标将根据交互发生的位置改变距离

5.2.23、setCursorFixedDistance:设置光标和相机的距离为一个固定值

5.2.24、setRaycasters:替换射线集合

5.2.25、getLastLocalIntersect:获取最后一次光标的坐标

5.2.26、updateLastHit:更新最后一个命中对象和视图的层次结构。 创建交互事件,然后分发给GuiSys的监听事件

六、ReactNativeContext


ReactNativeContext

ReactNativeContext是在VRInstace里面创建跟视图里面实例化的,显示调用ReactNativeContext的registerModule注册模块,然后init初始化,最后 调用createRootView创建根视图,然后调用frame方法

这个上下文对象主要是和react bundle进行沟通的,往react来回传递消息的;同时就是异步的工作在文本worker里面,这样主线程UI和浏览器的渲染线程就不会因为工作在react内部而被打断。

在构建时,上下文将启动WebWorker并注册回调以进行处理。 在`frame`函数中处理的消息;

因为webworker异步运行时,从React调用调出都是隐藏的,所以不会有返回值,应该使用JavaScript回调和附加消息来处理响应;

有以下几种方法在这个RN的上下文中:

6.1、构造函数要传过来3个参数,一个是guisys,一个是bridgeurl,一个是option;

主要做的事就是三件,注册模块组件、利用guisys监听GuiSysEvent和UIViewEvent事件、注册工人的onmessage函数,接收到执行指令‘exec’没有立即处理消息,而是放到消息队列中分发给frame函数来处理;

下面先来看下构造函数中实例化的各种模块:

UIManager:管理各种UI组件的;

Timing:定时模块允许浏览器客户端将React定时器与客户端的帧速率同步;

VideoModule:视频模块;

AudioModule:音频模块;

GlyphTextures:直译过来就是:雕刻纹理,这是用canvas画图的原生module,画的图贴在模型或者哪个地方的,后面用到了再讲;

HeadModel:这个类主要是拿到相机的位置和头部的位置,接受topHeadPose事件,同时发送onReceivedHeadMatrix事件,把头部坐标和相机的参数发送出去;

TextureManager:这是纹理管理器,管理远程或者内存中的纹理,并确保在合适的时候在mesh和图像之间共享。

RCTResourceManager:一个映射处理React vr资源和协议字典的类,react native组件可以通过类似于"protocol://handle"这样的url来使用资源,不能用已经存在的协议“http/https/.”这样的协议来用做资源的协议。

RCTInputControls:React Naitve的输入事件管理器,发射输入事件到当前的聚焦的视图上;

AndroidConstants:android的常量,目前里面及一个常量,版本号:22

AsyncLocalStorage:本地异步存储,是异步存储的实现,是建立在IndexDB的基础上的,他的方法不能直接被调用的,只能在React这边远程的被AsyncStorage调用。

ControllerInfo:这个是暴露链接手柄和控制器的方法,监听响应控制器连接/断开事件,并提取有关控制器的静态信息(唯一标识符,按钮和轴计数,左侧和右侧等),把静态信息发送出去。对于控制器按钮状态和姿势,还要依赖于React VR的输入事件和射线系统。

History:暴露浏览器的历史栈给React,包含浏览器历史长度、状态、

前进、后退、替换等等;

Networking:这是React Native的网络接口的实现,这些方法也不能直接用,只能通过React那边的Networking来调用,这个模块是基于fetch方法的,响应的结果和发送的请求通过消息返回给react那边。

LinkingManager:这和React Native的linking类似,用来打开Url,能否打开Url、获取初始的Url,该模块不是直接调用,而是通过React代码在内部进行调用。

Location:实现了window的location,给React 上下文用的,可以从react vr打开另外的网址,有两个方法,一个是刷新,一个是替换;

WebSocketModule:React Native的websocket接口的实现,方法有:建立连接通道、发送数据、发送二进制数据通过message被react调用、关闭通道、ping暂时不能用;

ReactVRConstants:包含VR这边几个参数,版本号:0.1.0;运行环境:WebVR;运行环境的版本:0.1.0;用户代理:就是导航(navigator)的代理;平台:导航里面的平台。

RCTExceptionsManager:用于处理异常报告的模块;

RCTSourceCode:源代码模块允许React代码查找源映射,

ExternalAssets:外部资源加载管理,里面就是设置assetRoot,资源的根目录;

6.2、init初始化:

搬运工发送moduleConfig指令,传递原生模块;

搬运工发送bundle传递bundle;

如果热更新开启,还调用HMRClient的enable方法,传递bundle的url的一堆信息过去

6.3、shutdown:调用每个模块的shutdown关闭react native上下文对象

6.4、createRootView:创建根视图

首先搬运工发送执行命令,调用AppRegistry模块的的runApplication方法,传递组件名和初始的属性;

然后调用UIManager的创建根视图方法创建跟视图;

最后返回rootview的tag标识;

6.5、updateRootView:更新根视图

搬运工发送执行命令,调用AppRegistry模块的的runApplication方法,传递前面创建的根视图的组件和新的属性;

6.6、destroyRootView:删除根视图及子视图

搬运工发送执行命令,调用AppRegistry模块的的unmountApplicationComponentAtRootTag方法

6.7、frame

如果当前命中的视图正在侦听,则发送当前光标位置;

搬运工发送flush指令,然后循环处理搬运工接受到的消息;

然后分别调用UIManager、HeadModel、VideoModule、AudioModule、TextureManager的frame方法;

用当前场景的transform刷新相机的父组件,如果没有场景,或者场景没有transform属性,或者相机已经有了一个父组件了,就不用刷新了

6.8、getHitTag:

返回最靠近的view的tag标识

6.9、callFunction:调用函数

搬运工发出执行指令,调用模块的方法,并把参数传递给这个方法;

6.10、invokeCallback:在react内部调用指定的回调

6.11、registerModule:注册模块,把模块都加到一个数组里面

6.12、registerTextureSource:注册纹理资源


7、UIManager(视图管理器)


这个是从ReactNativeContext中先调用UIManager的createRootView创建根视图、然后在调用UIManager的frame的方法。下面方法也先讲这两个。

这里主要做的工作就是接收从js传过来的React指令然后传递给正在运行的原生视图。

这里面的有些方法可以是全局的被外部的调用的,但是大部分都是通过messages的形式在react那边被调用的。

视图与react版本的协调是通过react标签,由react代码管理的唯一ID。

UIManager还基于flexbox来布局view,里面有各种各样的测量方法。

下面先来逐一介绍这个视图管理器的构造函数和方法:

7.1、构造函数:

7.1.1、首先拿到上下文对象和guisys、定义几个事件类型、再定义包含视图的views、包含视图类型的对象等等。

7.1.2、然后注册各种原生视图和自定义视图:包含(RCTView、LiveEnvCamera、RCTImageView、Pano、Model、Scene、Sound、RCTText、RCTRawText、Video、VideoPano、AmbientLight、DirectionalLight、PointLight、SpotLight、CylindricalPanel、Box、Cylinder、Plane、Sphere、Prefetch)

7.2、createRootView:创建根视图

两行代码:

1、创建默认的RCTView;

2、把这个view添加到guisys里面去

7.3、createView:创建视图

做了5件事

1、如果视图存在就添加tag属性到Three.js的view上

2、记录创建的视图的类型

3、记录后面要寻找的类型的tag

4、管理视图的默认属性

5、给视图标记成dirty

7.4、updateView:将属性应用到是视图上

7.5、frame

调用每一个view的frame方法,然后布局每一个view

7.6、layout

循环所有的视图用css-layout布局这些视图

7.7、presentLayout:将布局呈现给从根到子的视图实现

简单来讲就是拿到上下左右、边框、可见与否、边角半径等等,然后设置给视图

7.8、setChildren:把子成员的tag设置给tag

7.9、manageChildren:管理成员

move 移动成员

add 添加成员

移除 标记要移除的成员

purgeView 移除视图和下面的子视图

7.10、purgeView 移除视图和下面的子视图

7.11、registerViewType

注册视图类型和创建视图的方法

7.12、removeRootView

删除根视图 purgeView

7.13、replaceExistingNonRootView

移动新的视图tag到原有的tag上,然后调用manageChildren移动视图

7.14、removeSubviewsFromContainerWithID

移除view的所有子视图

7.15、getSceneCameraTransform

返回根tag下面的的第一个场景的transform

7.16、getLayers

返回曲面平面视图

7.17、setCursorVisibility

设置guisys的光标的可见与否

7.17、measureTextHeight

测量字体的高度

7.18、setBoundingBoxVisible

移除或者增加边框mesh,也就是矩形,可以用在调试时给一些组件高亮显示

7.19、measure

确定给定视图的屏幕,宽度和高度的位置,并通过异步回调返回值

7.20、measureInWindow

确定给定视图的屏幕,宽度和高度的绝对位置,并通过异步回调返回值

7.21、measureLayout

测量给定的视图和特定视图中的相对位置

7.22、measureLayoutRelativeToParent

测量给定的视图在父控件中的相对位置

7.23、configureNextLayoutAnimation

配置要用于原生布局更改的动画,以及创建原生视图

7.24、dispatchViewManagerCommand

给指定的原生视图一个指令,可以使从js那边调用的回调函数

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容