Обнаружить этап оставления мыши при перетаскивании в ActionScript 3
Event.MOUSE_LEAVE отлично подходит для ActionScript 3, но, похоже, он не срабатывает, если пользователь держит левый (или справа это пункт) кнопка мыши down.
Есть ли способ определить, покидает ли мышь фильм во время удержания мыши? Или если он выпущен за пределами флеш-ролика?
Ответы
Ответ 1
Чтобы получить все это, нужно немного взломать. Вы должны сохранить, находится ли мышь вне сцены или нет, и обрабатывать событие Event.MOUSE_LEAVE
соответственно. Выполнение этого способа дает вам все обычные функции мыши, в том числе не останавливая перетаскивание только потому, что мышь ушла с сцены. Поскольку пользователь может вернуться на сцену и продолжить перетаскивание, он ждет, пока пользователь не отпустит мышь на сцене или вне ее.
var mouseOffStage:Boolean;
var bonk:YourDisplayObject = new YourDisplayObject()
addChild(bonk);
bonk.addEventListener(MouseEvent.MOUSE_DOWN, function():void {
mouseOffStage = false;
bonk.startDrag();
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
stage.addEventListener(Event.MOUSE_LEAVE, mouseLeave);
stage.addEventListener(MouseEvent.MOUSE_OUT, mouseOut);
stage.addEventListener(MouseEvent.MOUSE_OVER, mouseOver);
})
private function mouseUp(e:MouseEvent) :void {
trace("Mouse Up On Stage")
bonk.stopDrag()
}
private function mouseLeave(e:Event) :void {
if(mouseOffStage){
trace("mouse up and off stage");
bonk.stopDrag();
}else{
trace("mouse has left the stage");
//no reason to stop drag here as the user hasn't released the mouse yet
}
}
private function mouseOut(e:MouseEvent) :void {
mouseOffStage = true;
trace("mouse has left the stage")
}
private function mouseOver(e:MouseEvent) :void {
mouseOffStage = false;
trace("mouse has come back on stage");
}
Взлом заключается в том, что событие MOUSE_LEAVE
, а не событие MOUSE_UP
, запускается, когда мышь выйдет из сцены, поэтому вам нужно отслеживать, была ли мышь уже выключена, когда она была выпущена.
после завершения перетаскивания вы, конечно же, хотите удалить все прослушиватели событий, связанные с обнаружением выходов и мышей, но этот код был оставлен для удобства чтения.
Ответ 2
вот что я делаю:
mc.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
private function onMouseDown(_e:MouseEvent):void
{
mc2.startDrag(params);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
stage.addEventListener(Event.MOUSE_LEAVE, onMouseLeave);
stage.addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
}
private function onMouseUp(_e:MouseEvent):void
{
ms2.stopDrag();
}
private function onMouseLeave(_e:Event):void
{
mc2.stopDrag();
}
private function onMouseOut(_e:MouseEvent):void
{
if (e.stageX <= 0 || e.stageX >= stage.stageWidth || e.stageY <= 0 || e.stageY >= stage.stageHeight)
{
mc2.stopDrag();
}
}
Ответ 3
Здесь пара сложных ловушек не попадает в:
Одна странная вещь: в Chrome + Firefox событие MOUSE_LEAVE не отправляется для WMODE OPAQUE
или TRANSPARENT
. Он просто не срабатывает - мышь вниз или вверх.
С WINDOW
он работает нормально. Мне понадобилось много времени, чтобы узнать! grr... http://bugs.adobe.com/jira/browse/FP-892
Во-вторых, убедитесь, что вы используете Event
для типа параметра для вашего обработчика Event.MOUSE_LEAVE
, а не MouseEvent
. Если вы попытаетесь обработать MOUSE_LEAVE
с помощью e:MouseEvent
, вы получите сообщение об ошибке, которое вы никогда не увидите (если вы не используете проигрыватель debug flash player). Это очень простая ошибка, потому что вы, вероятно, указываете на все ваши другие обработчики на тот же метод.
Вот что я делаю: (просто назовите мой основной endDrag
из mouseLeave(e:Event)
stage.addEventListener(MouseEvent.MOUSE_MOVE, drag);
stage.addEventListener(MouseEvent.MOUSE_UP, endDrag);
stage.addEventListener(Event.DEACTIVATE, endDrag);
stage.addEventListener(Event.MOUSE_LEAVE, mouseLeave);
private function mouseLeave(e:Event):void
{
endDrag(new MouseEvent("MOUSE_LEAVE"));
}
public function endDrag(evt:MouseEvent):void
{
/// handle end drag
}
Ответ 4
Я столкнулся с аналогичной проблемой в средстве просмотра типа PDF, которое мне пришлось создать в приложении Flex. Я хотел, чтобы функции панорамирования все еще работали, даже если мышь покинула сцену или окно браузера. Вот как я это сделал, я изменил код, чтобы удалить ссылки на классы Flex Framework, поэтому это должно быть применимо к любому проекту AS3. В mouseDown
я начну отслеживать эти значения по таймеру. _client
может быть любым flash.display.DisplayObject
на целевом этапе. В моем случае это был объект Flex mx.controls.SWFLoader
, но в вашем случае я предполагаю, что это будет цель перетаскивания:
private function get currentMouseX():Number
{
return _client.stage.mouseX;
}
private function get currentMouseY():Number
{
return _client.stage.mouseY;
}
Значения stage.mouseX
и stage.mouseY
определяются относительно стадии, находится ли мышь в стадии или даже в окне браузера (по крайней мере, в Flash Player 10, я не тестировал это в более ранних версиях проигрывателя Flash Player). Чтобы увидеть, находится ли мышь вне сцены, просто проверьте и посмотрите, находятся ли эти значения в стадии, например:
if (currentMouseY < 0 ||
currentMouseY > _client.stage.height ||
currentMouseX < 0 ||
currentMouseX > _client.stage.width)
{
// Do something here
}
РЕДАКТИРОВАТЬ: Что касается обнаружения события mouseUp
вне сцены, если вы регистрируете прослушиватель на сцене, вызывается mouseUp, даже если это событие происходит за пределами сцены или браузера. Вот код для того, как я обрабатываю функцию событий для справки. Объектом _client
может быть любой flash.display.DisplayObject
:
// attach the events like so when you initialize
_client.addEventListener(MouseEvent.MOUSE_DOWN , handleMouse);
_client.addEventListener(MouseEvent.MOUSE_OUT , handleMouse);
_client.addEventListener(MouseEvent.MOUSE_OVER , handleMouse);
//
// and handle them like this:
private function handleMouse(e:MouseEvent):void
{
switch(e.type)
{
case "mouseDown":
// add listeners, notice the mouse move and mouse up are
// attached to the stage, not the display object this way
// events are issued regardless of whether the mouse is in
// the stage or even within the browser window
_client.stage.addEventListener(MouseEvent.MOUSE_UP, handleMouse);
_client.addEventListener(MouseEvent.CLICK, handleMouse);
_client.stage.addEventListener(MouseEvent.MOUSE_MOVE, handleMouse);
// remove listeners
_client.removeEventListener(MouseEvent.MOUSE_DOWN, handleMouse);
//
// commands / actions
break;
case "mouseUp":
// add listeners
_client.addEventListener(MouseEvent.MOUSE_DOWN, handleMouse);
// remove listeners
_client.stage.removeEventListener(MouseEvent.MOUSE_UP, handleMouse);
_client.stage.removeEventListener(MouseEvent.MOUSE_MOVE, handleMouse);
// commands/actions
break;
case "click":
// add listeners
_client.addEventListener(MouseEvent.DOUBLE_CLICK, handleMouse);
// remove listeners
_client.removeEventListener(MouseEvent.CLICK, handleMouse);
// commands / actions
break;
case "mouseMove":
// add listeners
// remove listeners
_client.stage.removeEventListener(MouseEvent.MOUSE_MOVE, handleMouse);
_client.removeEventListener(MouseEvent.CLICK, handleMouse);
// commands
break;
case "mouseOut":
// add listeners
// remove listeners
// commands / actions
break;
case "mouseOver":
// add listeners
// remove listeners
// commands /actions
break;
}
}
EDIT: удалены ссылки на классы фрейма Flex
EDIT: Я помню, что может возникнуть проблема с событиями за пределами окна браузера, когда приложение запускается в браузере Safari на Mac OSX. Убедитесь, что вы проверили этот код в этом браузере, если используете его. Это не было проблемой в моем приложении, поэтому я больше не рассматривал этот вопрос.
Ответ 5
Если вы делаете что-то там, где вы перетаскиваете MovieClip, это выглядит хорошо.
stage.addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
РЕДАКТИРОВАТЬ - неважно
Ответ 6
Есть ли способ определить, покидает ли мышь фильм во время удержания мыши?
Не знаю, что я знаю
Или, если он выпущен за пределами флеш-ролика?
Событие .MOUSE_LEAVE происходит, когда вы отпускаете снаружи.
больше информации здесь
http://blog.zupko.info/?p=3
см. комментарий JIMISAACS.
Ответ 7
var youMax_X:Number; //set this var to Max x
var youMax_Y:Number; //set this var to `enter code here`Max y
var dragBounds:Rectangle = new Rectangle(0,0,youMax_X,yourMax_Y);
stage.addEventListener(MouseEvent.MOUSE_DOWN,handleDown);
stage.addEventListener(MouseEvent.MOUSE_UP,handleUp);
private function handleDown(e:Event):void{
this.startDrag(false,dragBounds);
}
private function handleUp(e:Event):void{
this.stopDrag();
}
Ответ 8
Вот правильный ответ. Пользовательский класс, с которым вы передаете DisplayObject, будет перетаскивать его до мышки или мыши из-за сцены. Настройте по желанию:
package fanlib.gfx
{
import flash.display.DisplayObject;
import flash.display.Stage;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.ui.Mouse;
public class Drag
{
private var obj:DisplayObject;
private var point:Point = new Point();
private var stg:Stage;
public function Drag(obj:DisplayObject)
{
this.obj = obj;
stg = Stg.Get();
stg.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
stg.addEventListener(MouseEvent.MOUSE_UP, stopDrag);
//stg.addEventListener(Event.MOUSE_LEAVE, stopDrag); // sh*t just won't fire
point.setTo(stg.mouseX, stg.mouseY);
}
private function mouseMove(e:MouseEvent):void {
if (stg.mouseX <= 0 ||
stg.mouseY <= 0 ||
stg.mouseX >= stg.stageWidth ||
stg.mouseY >= stg.stageHeight) {
stopDrag();
return;
}
obj.x += stg.mouseX - point.x;
obj.y += stg.mouseY - point.y;
point.setTo(stg.mouseX, stg.mouseY);
}
public function stopDrag(e:* = null):void {
stg.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
stg.removeEventListener(MouseEvent.MOUSE_UP, stopDrag);
//stg.removeEventListener(Event.MOUSE_LEAVE, stopDrag);
}
}
}