Пользовательский графический курсор

Апрель 5th, 2010 автор: Oleg Antipov

Обычный системный курсор как то не особо выделяется красотой, поэтому вполне понятно стремление разработчиков flash игр сделать свой собственный графический курсор. На первый взгляд ничего сложного в этом нет однако есть пара тонкостей, про которые многие забывают.

Для начала располагаем в самом верхнем слое на временной линейке наш мовиклип cursor, потом прячем системный курсор (класс Mouse находится в библиотеке flash.ui):

Mouse.hide();



И вешаем перемещение мовиклипа курсора на событие MOUSE_MOVE:

function mouseMove(e:Event):void
{
	cursor.x = e.stageX;
	cursor.y = e.stageY;
}
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove);



Или более изящный вариант, который мне больше нравится:

cursor.startDrag(true);



Вроде бы как и всё, посмотрим что получилось:

Что это за чертовщина? Почему кнопки не нажимаются и выделение мигает?! Причина на самом деле банальней некуда – наш графический курсор это тоже мовиклип, который по умолчанию ловит события MOUSE_MOVE и CLICK поэтому надо просто отключить для мовиклипа cursor обработку событий мыши:

cursor.mouseEnabled = false;
cursor.mouseChildren = false;



Следующая проблема заключается в том, что при нажатии правой кнопки вылетает контекстное меню флеш плеера и после его закрытия у нас опять появляется системный курсор. Чтобы этого не происходило просто будем его прятать при каждом клике по сцене:

function mouseClick(evt:Event):void
{
	cursor.visible = true;
	Mouse.hide();
}
stage.addEventListener(MouseEvent.CLICK, mouseClick);



Ну и последний косяк – если мышь вывести за пределы флешки – мовиклип курсора остаётся висеть там, где последний раз был системный курсор. С помощью обработки события сцены MOUSE_LEAVE нужно прятать мовиклип курсора, а после в событии MOUSE_MOVE показывать его вновь:

function mouseLeave(e:Event):void
{
	cursor.visible = false;
	stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseBack);
}
stage.addEventListener(Event.MOUSE_LEAVE, mouseLeave);
 
function mouseBack(e:Event):void
{
	cursor.visible = true;
        Mouse.hide();
	stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseBack);
}



Вот впринципе и всё. Финальный результат без косяков:

Полный код примера:

//Прячем курсор мыши
Mouse.hide();
 
//Привязываем мовиклип к системному курсору
cursor.startDrag(true);
 
//Отключаем все события мыши для мовиклипа курсора
cursor.mouseEnabled = false;
cursor.mouseChildren = false;
 
//По клику на сцене опять прячем курсор
function mouseClick(evt:Event):void
{
	cursor.visible = true;
	Mouse.hide();
}
stage.addEventListener(MouseEvent.CLICK, mouseClick);
 
//Если курсор вышел за пределы флешки - прячем его
//И ставим обработчик события MOUSE_MOVE чтобы обработать
//возвращение курсора 
function mouseLeave(e:Event):void
{
	cursor.visible = false;
	//ставим обработчик события MOUSE_MOVE чтобы показать курсор вновь при наведении на флешку.
	stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseBack);
}
stage.addEventListener(Event.MOUSE_LEAVE, mouseLeave);
 
//Если курсор вернулся на флешку - показываем его вновь
function mouseBack(e:Event):void
{
	cursor.visible = true;
        Mouse.hide();
	//обработчик события MOUSE_MOVE удаляем за ненадобностью
	stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseBack);
}



Сам пример можно скачать здесь: http://www.anegmetex.com/devblog/files/customCursor.rar

Категория: Хитрости

16 Комментариев

  1. Platon

    cursor.mouseEnabled = false;
    cursor.mouseChildren = false;

    Не знал, делал по-другому, сдвигая на несколько пикселей курсор вниз и вправо. Пасиба :)

  2. Oleg Antipov

    А я вот когда делал долго не мог понять почему у меня кнопочки перестали кликаться )

  3. Claymore

    Если пользователь выберет пункт в контекстном меню или отменит его кликом за пределами флешки появится системный курсор.

    Для фикса можно в функцию mouseBack добавить Mouse.hide();

  4. Oleg Antipov

    Спасибо, обновил пост :)

  5. Vovka

    Что за клоуны там у них работает, в этом adobe??? Вызываем контекстное меню, нажимаем escape, курсор остаётся.

  6. Лев

    Большое спасибо автору!!! Долго искал причину, проблем с собственным курсором.
    У меня даже Mouse.hide() не работал,
    пока не добавил
    cursor.mouseEnabled = false;
    cursor.mouseChildren = false;

  7. serg

    а подскажите, как сделать что б при загрузке, не было видно курсора, до наведения на флешку?

  8. Oleg Antipov

    Можно мовиклипу курсора изначально задать положение за пределами видимости экрана… если конечно я правильно понял вопрос )

  9. serg

    _zircon.com.ua
    при загрузке, виден курсор, на обоих флешках на титульной странице,
    а хотелось бы, что б он появлялся только при наведении. Что то пробую и ниче не получется :(
    как задать? думал может, к примеру:

    cursor.x = -20;
    cursor.y = -20;

  10. Oleg Antipov

    Попробуй добавить на фрейм

    cursor.visible = false;
    stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseBack);

  11. serg

    спасибо, именно то что было нужно :arrow:

  12. ALexusB

    cursor.startDrag(true);
    Способ рабочий не всегда
    Потому неверный
    Такой курсор не таскает другие клипы Дропом, а зависает на месте до отпускания кнопки – видать фокус таскания единый.

    Так же после
    cursor.x = e.stageX;
    cursor.y = e.stageY;
    нужно делать
    e.updateAfterEvent();
    Иначе при малых кадрах (типа 10-20 кадров) будет тормозить курсор визуально (рваное движение).

    И вот тогда все будет ок
    До доработки Адобом нормальных курсоров, а не такого гемора.

    ЗЫ Блог интересный. Спасибо.

  13. Oleg Antipov

    спасибо за полезный комментарий :)

  14. Татьяна

    Спасибо за полезную информацию! Только у вас удалось найти все ответы на все интересующие вопросы.

  15. romamik

    Небольшое дополнение: MOUSE_LEAVE не выстреливает, если кнопка мыши нажата в момент вывода курсора за пределы флешки. Точнее выстреливает, но только после отпускания мышки. Что я с этим сделал тут: http://flashgameblogs.ru/blog/actionscript/838.html

  16. Kvant

    Oleg Antipov всё гораздо проще:
    1) Рисуем курсор
    2) преобразуем его в “фрагмент ролика”
    3) Вводим AS:
    Mouse.hide();
    cursor.startDrag(true);

    //курсор готов

Оставить комментарий