用WebSocket接收服务器数据并控制W…

来源:互联网 发布:php flash播放mp4 编辑:程序博客网 时间:2024/06/11 22:45

用WebSocket接收服务器数据并控制WebGL渲染的模型时发生UncaughtTypeError: Uncaught TypeError: Cannot read property 'rotation' ofundefined问题

用WebSocket接收服务器数据并控制WebGL渲染的模型时发生Uncaught <wbr>TypeError: <wbr>Cannot <wbr>re

这个问题一直令我头疼了很久。最终发现是渲染与websocket连接顺序的问题。

当websocket服务器打开,websocket页面client能够正常链接的时候,反倒会导致加载完的模型是个null,真是不太懂里面的基本原理。最开始的时候,我的websocket系列初始化和定义函数是写在最开头的:

function initThree() {
           renderer=new THREE.WebGLRenderer({antialias:true});
           renderer.setSize(windows.innerWidth, windows.innerHeight );
           renderer.setClearColor(0xdddddd, 1.0);
           renderer.shadowMapEnabled = true;
           document.getElementByIdx_x_x_x_x_x_x("canvas3d").a(renderer.domElement);

 

           websocket = new WebSocket(wsUri);
           websocket.onopen = function(evt) { onOpen(evt) };
           websocket.onclose = function(evt) { onClose(evt) };
           websocket.onmessage = function(evt) { onMessage(evt) };
           websocket.onerror = function(evt) { onError(evt) };
}

 

于是每次链接上服务器后,webGL能不能渲染出模型都得靠运气。一般第一个网页准失败,第二或者第三个才能正常运行。链接不上服务器的时候基本webGL都能渲染,可以确定是websocket和webgl协作的时候出了什么问题。之后调换了下顺序:

 

function threeStart() {
           initThree();
           initCamera();
           initScene();
           initLight();
           initObject();

 

           websocket = new WebSocket(wsUri);
           websocket.onopen = function(evt) { onOpen(evt) };
           websocket.onclose = function(evt) { onClose(evt) };
           websocket.onmessage = function(evt) { onMessage(evt) };
           websocket.onerror = function(evt) { onError(evt) };
           render();

}

 

发觉还是老问题。百思不得其解。如果把render调换到newWebSocket的前面,的确可以运行,但是WebSocket罢工了,压根不运行。最终发现,render必须放在newWebSocket的后面,系列websocket定义函数的前面,也就是夹在之中

 

function threeStart() {
           initThree();
           initCamera();
           initScene();
           initLight();
           initObject();

 

           websocket = new WebSocket(wsUri);

           render();
           websocket.onopen = function(evt) { onOpen(evt) };
           websocket.onclose = function(evt) { onClose(evt) };
           websocket.onmessage = function(evt) { onMessage(evt) };
           websocket.onerror = function(evt) { onError(evt) };

}

 

但……这并没有从根本上解决加载不上的问题:于是,最佳方式是判断加载完以后再来渲染render:

参考链接:loader.onLoadComplete=function(){scene.add( mesh)}

这样就顺利多了。但,还有个问题,浏览器不报错、也不显示

 

添加setTimeOut函数,将更改角度的函数塞进Js单线程执行队列里面:

var monkeyRotate=function(){
           monkey.rotation.y -= gypoY * 0.03;

}
var render=function() {
           requestAnimationFrame(render);
           setTimeout(monkeyRotate,0);

}

 

WebSocket部分函数都塞到模型加载完以后运行

 

loader2.onLoadComplete=function(){
               scene.add(monkey);

               //Initial of WebSocket Client
               websocket = new WebSocket(wsUri);
               //Block problem: The render function should be at the between ofnew WebSocket and 'on' series function (onopen, onclose, onmessage,onerror, etc)
               websocket.onopen = function(evt) { onOpen(evt) };
               websocket.onclose = function(evt) { onClose(evt) };
               websocket.onmessage = function(evt) {
                   setTimeout(onMessage(evt),0);
               };
               websocket.onerror = function(evt) { onError(evt) };

}

 

这样处理后,谷歌浏览器中加载模型的成功率从60%提高到90%左右。

最终解决办法是把服务器端的发送消息标准化。由于发来的消息不仅仅包含double类型的传感器数据,还包含了hi howareyou这样的文字数据,当处理到文字数据的时候,javascript会发生类型转换错误,导致rotation属性丢失。解决后成功率100%

0 0