简体   繁体   English

自定义鼠标光标+ IE出现问题

[英]Custom mouse cursor + IE woes

I'm working on a project that has these attributes: 我正在一个具有以下属性的项目:

  1. jQuery driving the page jQuery驱动页面
  2. Unity 3d player embedded to the page using jQuery and unityobject.js (per instruction from Unity) 使用jQuery和unityobject.js嵌入到页面的Unity 3d播放器(来自Unity的指令)
  3. Unity has custom mouse cursor when user's cursor is inside of Unity's canvas area 当用户的光标位于Unity画布区域内时,Unity具有自定义鼠标光标

Issue: Unity captures the mouse cursor but won't release it when the web page that contains it becomes inactive. 问题: Unity捕获鼠标光标,但包含它的网页处于非活动状态时不会释放它。 This means if the user switches to a different tab (or opens a new window), the mouse cursor disappears when the user mouses over the area where Unity would have been. 这意味着,如果用户切换到其他选项卡(或打开新窗口),则当用户将鼠标移至Unity所在的区域时,鼠标光标将消失。 This is a unity bug described here in Unity 3d forum: http://forum.unity3d.com/threads/4565-Unity-Web-player-issue-mouse-hidden-for-all-new-windows 这是Unity 3d论坛中此处描述的一个统一错误: http : //forum.unity3d.com/threads/4565-Unity-Web-player-issue-mouse-hidden-for-all-new-windows

And no, it's still not fixed in the latest version of Unity web client. 不,它在最新版本的Unity Web客户端中仍未修复。

To mitigate the issue, we decided to have Unity listen to the current browser window status via Javascript and capture/release the custom mouse cursor based on the status it receives. 为了缓解此问题,我们决定让Unity通过Java脚本侦听当前浏览器窗口的状态,并根据其收到的状态捕获/释放自定义鼠标光标。 But there are other issues: 但是还有其他问题:

How Unity receives window status: Unity如何接收窗口状态:

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

I've tried the following methods... 我尝试了以下方法...

Method 1: Binding events to the "window" object 方法1:将事件绑定到“窗口”对象

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

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

The problem: in IE7 and IE8, new browser tabs aren't considered different "window", so the code has no effect on Unity. 问题:在IE7和IE8中,新的浏览器选项卡不被视为不同的“窗口”,因此代码对Unity没有影响。 It only works if a true separate browser window was open. 仅在打开一个单独的真正的浏览器窗口时才起作用。


Method 2: Binding events to the "document" object 方法2:将事件绑定到“文档”对象
Like such: $( document ).live(...); 像这样: $( document ).live(...);

The problem: $( document ) in jQuery actually does nothing. 问题: jQuery中的$( document )实际上什么也没做。 Found out the hard way. 找出困难的方法。
Source: http://forum.jquery.com/topic/should-document-live-map-to-document-bind-window-too 来源: http//forum.jquery.com/topic/should-document-live-map-to-document-bind-window-too


Method 3: Binding events to the <body> object 方法3:将事件绑定到<body>对象
Like such: $( 'body' ).live(...); 像这样: $( 'body' ).live(...);

The problem: Somehow IE doesn't recognize that the Unity object is part of the DOM (despite the use of the .live() method). 问题:以某种方式,IE无法识别Unity对象是DOM的一部分(尽管使用了.live()方法)。 So every time user clicks on the embedded Unity player, the browser sends a blur event to Unity, and the mouse cursor gets locked up ( console.log() prints out inactive when Unity is clicked on). 因此,每当用户单击嵌入式Unity播放器时,浏览器就会将blur事件发送到Unity,并且鼠标光标会被锁定(当单击Unity时console.log()打印inactive )。 And in some cases it won't even release the mouse cursor, rendering the entire browser unresponsive to mouse events; 在某些情况下,它甚至不会释放鼠标光标,从而使整个浏览器对鼠标事件无响应; the only way to release the cursor is to click outside of the browser window and click on the browser again). 释放光标的唯一方法是在浏览器窗口之外单击,然后再次单击浏览器。


Other things I've tried: 我尝试过的其他方法:

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

The problem: .addEventListener() method is not supported in IE on those elements at all! 问题: IE在这些元素上根本不支持.addEventListener()方法! GAH! GAH!


Bonus: 奖金:
The more observant of you may chime in a say, "Hey, why not detect the mouse click event on the Unity object itself and ignore the blur event, .live() or .bind() events." 观察力更强的人可能会说:“嘿,为什么不检测Unity对象本身上的鼠标单击事件,而忽略blur事件, .live().bind()事件。” Tried that. 试过了。 IE doesn't like it either. IE也不喜欢。 It completely ignores the event and says those events are not available for the object. 它完全忽略该事件,并说这些事件不适用于该对象。

So my fellow Javascript gurus. 我的Java专家也是如此。 I'm out of ideas as how to best approach this problem in an elegant way. 我没有办法以一种优雅的方式最好地解决这个问题。 Any pointers would be appreciated. 任何指针将不胜感激。

Problem solved. 问题解决了。 A solution was provide on Unity3d's forum buried down somewhere... http://forum.unity3d.com/threads/27516-Mouse-input-possible-from-different-tab 埋在某处的Unity3d论坛上提供了一种解决方案... http://forum.unity3d.com/threads/27516-Mouse-input-possible-from-different-tab

The gist of it is: Frameworks are not always the answer. 其要旨是: 框架并非总是答案。 Go back to the roots. 回到根源。

I'd forgotten that the .addEventListener() is not native to IE, .attachEvent() is. 我忘了的.addEventListener()是不是原产于IE, .attachEvent()是。 So my code above would have worked had I just replaced all the event listeners with IE-specific ones when IE is detected. 因此,如果我仅在检测到IE时将所有事件侦听器替换为IE特定的事件侦听器,那么上面的代码就可以工作。

So the modified code is as follow: 因此修改后的代码如下:

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' );
}

To truly make this work, you'd have to make the event attachments in a callback function of the unityobject.embedUnity() method. 要真正做到这一点,您必须在unityobject.embedUnity()方法的回调函数中创建事件附件。 If you try to attach the events prior to Unity being loaded, the browser will complain that GetUnity() is null or undefined . 如果您尝试在加载Unity之前附加事件,浏览器将抱怨GetUnity()nullundefined

Hope this helps someone scratching his head out there with the same issues. 希望这可以帮助某人在遇到同样问题时挠头。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM