Пользовательский курсор мыши + IE горе - PullRequest
2 голосов
/ 08 апреля 2011

Я работаю над проектом, который имеет следующие атрибуты:

  1. jQuery, управляющий страницей
  2. Unity 3D-плеер, встроенный в страницу с использованием jQuery и unityobject.js (за инструкциюиз Unity)
  3. Unity имеет пользовательский курсор мыши, когда курсор пользователя находится внутри области холста Unity

Проблема: Unity захватывает курсор мыши, но не освобождаетэто когда веб-страница, которая содержит его, становится неактивной.Это означает, что если пользователь переключается на другую вкладку (или открывает новое окно), курсор мыши исчезает, когда пользователь наводит курсор на область, где находился бы Unity.Это ошибка единства, описанная здесь на форуме Unity 3d: http://forum.unity3d.com/threads/4565-Unity-Web-player-issue-mouse-hidden-for-all-new-windows

И нет, она все еще не исправлена ​​в последней версии веб-клиента Unity.

Чтобы решить эту проблему, мы решиличтобы 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(...);

Проблема: $( document ) в jQuery фактически ничего не делает.Обнаружил трудный путь.
Источник: http://forum.jquery.com/topic/should-document-live-map-to-document-bind-window-too


Метод 3: Связывание событий с <body> объектом
Примерно так: $( 'body' ).live(...);

Проблема: Каким-то образом IE не распознает, что объект Unity является частью DOM (несмотря на использование метода .live()).Поэтому каждый раз, когда пользователь нажимает на встроенный проигрыватель Unity, браузер отправляет событие blur в Unity, и курсор мыши блокируется (console.log() печатает inactive при нажатии на Unity).И в некоторых случаях он даже не отпустит курсор мыши, что делает весь браузер невосприимчивым к событиям мыши;единственный способ освободить курсор - щелкнуть за пределами окна браузера и снова щелкнуть в браузере).


Другие вещи, которые я пробовал:

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 Ответ

1 голос
/ 08 апреля 2011

Проблема решена. Решение было предоставлено на форуме 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() - это null или undefined.

Надеюсь, это поможет кому-то почесать голову там с такими же проблемами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...