自定义鼠标光标+ IE困境

时间:2011-04-08 02:23:50

标签: javascript internet-explorer unity3d unityscript

我正在开发一个具有以下属性的项目:

  1. jQuery驾驶页面
  2. 使用jQuery和unityobject.js(来自Unity的每条指令)
  3. 将Unity 3d播放器嵌入到页面中
  4. 当用户的光标位于Unity的画布区域内时,Unity具有自定义鼠标光标
  5. 问题: Unity捕获鼠标光标但在包含它的网页变为非活动状态时不会释放它。这意味着如果用户切换到不同的选项卡(或打开一个新窗口),当用户将鼠标移动到Unity所在的区域时,鼠标光标就会消失。这是Unity 3d论坛中描述的统一错误: http://forum.unity3d.com/threads/4565-Unity-Web-player-issue-mouse-hidden-for-all-new-windows

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

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

    Unity如何接收窗口状态:

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

    我尝试过以下方法......

    方法1:将事件绑定到“窗口”对象

    $( 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不知道Unity对象是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() {...} );
    

    问题: .addEventListener()方法在IE上根本不支持这些元素!的 GAH!


    加成:
    你观察得更加敏锐,可能会说:“嘿,为什么不检测Unity对象本身的鼠标点击事件而忽略blur事件,.live().bind()事件。”试过了。 IE也不喜欢它。它完全忽略了该事件,并说这些事件不适用于该对象。

    所以我的Javascript大师。我没有想法如何以优雅的方式最好地解决这个问题。任何指针都会受到赞赏。

1 个答案:

答案 0 :(得分: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

希望这有助于某些人在同样的问题上摸不着头脑。