2011-04-08 105 views
2

我的工作具有这些属性的项目:自定义鼠标光标+ IE愁楚

  1. 的jQuery驱动的页面嵌入到页面使用jQuery和unityobject.js
  2. 团结3D播放器(每个指令从Unity )
  3. 统一定制鼠标光标时用户的光标是统一的画布区域的内部

问题:统一捕获谋se光标,但当包含它的网页变为非活动状态时不会释放它。这意味着如果用户切换到不同的选项卡(或打开一个新窗口),当用户将鼠标放置在Unity所在的区域时,鼠标光标消失。这是在Unity3D论坛中描述的统一错误: http://forum.unity3d.com/threads/4565-Unity-Web-player-issue-mouse-hidden-for-all-new-windows

而且不,在最新版本的Unity Web客户端中仍然没有修复。

为了缓解这个问题,我们决定让Unity通过Javascript监听当前的浏览器窗口状态,并根据收到的状态捕获/释放自定义鼠标光标。但也有其他的问题:

团结如何接收窗口状态:

// GetUnity returns the Unity object in the DOM<br> 
NAMESPACE.windowStatus = function(statusStr) { 
    GetUnity().SendMessage("_AppShell", "OnRecieveWindowStatusFromWebPage", statusStr); 
} 

我尝试以下方法...

方法1:将事件绑定到了“window”object

$(window).live('focus', function() { 
    NAMESPACE.windowStatus('active'); 
}); 

$(window).live('blur', function() { 
    NAMESPACE.windowStatus('inactive'); 
}); 

问题:在IE7和IE8中,新的浏览器选项卡不被认为是不同的“窗口”,所以代码对Unity没有影响。它只在一个真正的单独的浏览器窗口打开时才起作用。


方法2:将事件绑定到 “文件” 对象
像这样的:$(document).live(...);

问题:jQuery的$(document)实际上什么也不做。发现困难的方式。
来源:http://forum.jquery.com/topic/should-document-live-map-to-document-bind-window-too


方法3:结合事件到对象<body>
像这样:$('body').live(...);

问题:不知何故IE不认识到,统一性对象是部分的DOM(尽管使用了.live()方法)。因此,每当用户点击嵌入式Unity播放器时,浏览器都会向Unity发送一个blur事件,并且鼠标光标被锁定(当单击Unity时,console.log()打印出inactive)。在某些情况下,它甚至不会释放鼠标光标,导致整个浏览器对鼠标事件无响应;释放光标的唯一方法是在浏览器窗口外单击并再次单击浏览器)。


其他的事情我已经试过:

window.addEventListener('focus', function() {...}); 
document.addEventListener('focus', function() {...}); 
document.body.addEventListener('focus', function() {...}); 
document.getElementsByTagName('body')[0].addEventListener('focus', function() {...}); 

问题:在IE浏览器不支持在所有这些因素.addEventListener()方法! GAH!


奖励:
更细心的你可能在说,“嘿,为什么不检测的统一的鼠标点击事件对象本身,而忽略了blur事件,.live().bind()事件帮腔“。试过了。 IE也不喜欢它。它完全忽略了事件,并说这些事件不适用于该对象。

所以我的同事的Javascript大师。我不知道如何以最好的方式最好地解决这个问题。任何指针将不胜感激。

回答

1

问题已解决。在Unity3d的论坛上提供了一个解决方案,它埋在某处... http://forum.unity3d.com/threads/27516-Mouse-input-possible-from-different-tab

它的要点是:框架并不总是答案。回到根源。

我忘记了.addEventListener()不是原生的IE,.attachEvent()是。所以我上面的代码可以工作了,当我检测到IE时,我用IE特定的事件监听器替换了所有的事件监听器。

所以修改后的代码如下:

if (navigator.appName == 'Microsoft Internet Explorer') { 
    GetUnity().attachEvent('onmouseover', onFocus, false); 
    GetUnity().attachEvent('onfocusin', onFocus, false); 
    GetUnity().attachEvent('onmouseout', onBlur, false); 
} else { 
    // Netscape, Firefox, Mozilla, Chrome and Safari. 
    GetUnity().addEventListener('mouseover', onFocus, false); 
    GetUnity().addEventListener('focus', onFocus, false); 
    GetUnity().addEventListener('mouseout', onBlur, false); 
} 

function onFocus() { 
    NAMESPACE.WindowStatus('active'); 
} 

function onBlur() { 
    NAMESPACE.WindowStatus('inactive'); 
} 

要真正使这项工作,你就必须让事件附件的unityobject.embedUnity()方法的回调函数。如果您尝试在Unity加载之前附加事件,浏览器将会抱怨GetUnity()nullundefined

希望这可以帮助别人在那里发现同样的问题。