Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   как сделать перемещение спрайта мышью (http://www.flasher.ru/forum/showthread.php?t=203502)

kelod 27.09.2013 04:24

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

собственно ничего сложного, я создал один спрайт, добавил в него спрайтов-потомков, повешал на них события разные, всё работает, но есть проблемы, которые уже два дня не могу решить((
перемеoение осуществляю используя start/stop drag, при уходе курсора мышки за экран, всё останавливается и скачет при возвращении, это первое, плюс необходимо осуществитьсброс перетаскивания, при попадании мышки на другой объект или выходу за пределы, пробовал вешать событие OUT, возникла проблема, фокус почему то определяется не у родителя, а у потомка, хотя слушатель на родителе

Код AS3:

addChild(fon);
fon.addChild(spt1);
fon.addChild(spt2);
fon.addChild(spt3);
 
fon.addEventListener(MouseEvent.MOUSE_DOWN, nach);
fon.addEventListener(MouseEvent.MOUSE_UP, kon);
fon.addEventListener(MouseEvent.MOUSE_OUT, kon);

вызов функций такой
Код AS3:

private function kon(e:MouseEvent):void 
                {
                        fon.stopDrag();
                }
 
                private function nach(e:MouseEvent):void
                {
                        fon.startDrag();
 
                }


TexHuK 27.09.2013 09:51

можно сделать так
Вешаем на спрайты потомок слушатель
Код AS3:

for (var i:int = 0; i < fon.numChildren-1; i++)
this["spritePotomok" + i].addEventListener(MouseEvent.MOUSE_DOWN, nach);

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

kelod 27.09.2013 14:34

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

Akopalipsis 27.09.2013 15:02

Код AS3:

package
{
        import flash.display.DisplayObject;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
 
        public class Drag extends Sprite
        {
                private var _container:Sprite;
                private var _spriteArray:Vector.<Sprite>;
 
                public function Drag()
                {
                        if (stage) init();
                        else addEventListener(Event.ADDED_TO_STAGE, init);
                }
 
                private function init(event:Event=null):void
                {
                        removeEventListener(Event.ADDED_TO_STAGE, init);
 
                        addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
 
 
                        _container = new Sprite();
                        super.addChild(_container);
                        var circle:Sprite;
                        _spriteArray = Vector.<Sprite>([]);
 
                        for (var i:int = 0; i < 10; i++)
                        {
                                circle = new Sprite();
                                circle.graphics.beginFill(Math.random() * 0xf6f6f6);
                                circle.graphics.drawCircle(Math.random() * stage.stageWidth, Math.random() * stage.stageHeight, 30);
                                circle.graphics.endFill();
                                _spriteArray.push(circle);
                                _container.addChild(_spriteArray[i] as DisplayObject);
                        }
                }
 
                private function mouseDownHandler(event:MouseEvent):void
                {
                        event.target.parent.startDrag();
                }
 
        }
 
}


kelod 27.09.2013 15:18

Akopalipsis, вопрос был про завершение перетаскивания, а не про его начало, начало перетаскивания я делаю так же
в ващем примере если добавитm событие out срыв мыши происходит так же как и у меня

TexHuK 27.09.2013 17:24

Цитата:

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

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

Если же роль сцены заключается лишь в том, что ее нужно таскать, при чем хватая в разных местах, будь то, объект, или просто пустая область, и больше не взаимодействовать с другими объектами, то достаточно наложить с верху прозрачный спрайт, который и будет отвечать за область захвата.

или вы хотите таскать всю область хватая любой объект при этом не вешая на них слушатель? так не получится.

kelod 27.09.2013 17:40

Цитата:

Сообщение от TexHuK (Сообщение 1147077)
я же не предлагаю вешать конкретно на все потомки.
если не вешать слушатели на потомки, остается таскать именно сцену, но слушатель может быть один, а в зависимости от выбранного объекта на сцене, выполнять предназначенный функционал.

Если же роль сцены заключается лишь в том, что ее нужно таскать, при чем хватая в разных местах, будь то, объект, или просто пустая область, и больше не взаимодействовать с другими объектами, то достаточно наложить с верху прозрачный спрайт, который и будет отвечать за область захвата.

или вы хотите таскать всю область хватая любой объект при этом не вешая на них слушатель? так не получится.

мне не нужно таскать сцену, мне нужно таскать спрайт, на которого добавлены другие спрайты, причём особенностью является то что добавленные спрайты закрывают спрайт родителя, с перетаскиванием проблем нет, проблема с прекращением онного, mouse_out работает для потомка а не для родителя, хотя вещаю на родителя

PS: я конечно написал костыль, который позволяет это обойти, но хотелось бы нормальное решение услышать

Babylon 27.09.2013 18:03

Код AS3:

public function mouseOut(event:Event):void
                {
 
                        this.mouseChildren = true
                        event.stopPropagation()
 
                }


Rivexe 27.09.2013 18:09

Проверяй с какого объекта пришло событие и является ли он потомком.

Код AS1/AS2:

function kon(e:MouseEvent):void
{
        if(e.target.parent == fon || (e.relatedObject && e.relatedObject.parent == fon))
                return;
        fon.stopDrag();
}


Babylon 27.09.2013 18:22

уберите страшный код пожалуйста:)

Akopalipsis 27.09.2013 18:33

Вообще у меня вопрос к опытным флешарам - Вы пользуетесь startDrag() ?
Код AS3:

event.stopPropagation()

Прекрастно подходит для кнопок, и когда ТС указал на мою невнимательность, я первое что хотел воплотить
это именно stopPropagation(). Но если его повесить на перетаскиваемый обьект, то он срабатывает от рывков. А если на что то другое, то обработчик событий не видет родителя таргет.

Babylon 27.09.2013 18:43

Ещё ребенок должен сообщить x,y дельты перемещений родителю

Добавлено через 1 минуту
это задача вариант трансформер менеджера

Rivexe 27.09.2013 18:49

Что Вас в нем так напугало?

Babylon 27.09.2013 19:07

Вы вероятно не поняли вопрос. Драгается ребенок, а родитель смещается на то расстояние, на которое смещается ребенок. Сам фон не драгается. Поэтому ему стоп драг не нужен.

kelod 27.09.2013 19:15

Цитата:

Сообщение от Babylon (Сообщение 1147093)
Вы вероятно не поняли вопрос. Драгается ребенок, а родитель смещается на то расстояние, на которое смещается ребенок. Сам фон не драгается. Поэтому ему стоп драг не нужен.

не кто не дёргается, рывки происходят при выходе мыши за стэйдж и возвращении назад в другом месте, основная проблема что происходит срыв мыши когда тянешь за ребёнка

Rivexe 27.09.2013 19:17

Видать я действительно что то не так понял. По первому посту и коду в нем подумал, что перемещаем именно родителя. Смысл двигать ребенка > потом двигать родителя > двигать всех остальных детей

Добавлено через 3 минуты
kelod, я привел пример кода, попробуйте его.

kelod 27.09.2013 19:21

Цитата:

Сообщение от Rivexe (Сообщение 1147097)
Видать я действительно что то не так понял. По первому посту и коду в нем подумал, что перемещаем именно родителя. Смысл двигать ребенка > потом двигать родителя > двигать всех остальных детей

мне вообще-то и нужно двигать родителя, но поверх родителя ребёнок, посему захватывает событие именно дитё, а не родитель((

Rivexe 27.09.2013 19:27

kelon, Ваш доработанный код:

Код AS3:

addChild(fon);
fon.addChild(spt1);
fon.addChild(spt2);
fon.addChild(spt3);
 
fon.addEventListener(MouseEvent.MOUSE_DOWN, nach);
fon.addEventListener(MouseEvent.MOUSE_UP, kon);
fon.addEventListener(MouseEvent.MOUSE_OUT, kon);

Код AS3:

private function kon(e:MouseEvent):void 
{
        fon.stopDrag();
}
 
private function nach(e:MouseEvent):void
{
        if(e.target.parent == fon || (e.relatedObject && e.relatedObject.parent == fon))
                return;
 
        fon.startDrag();
 
}


Akopalipsis 27.09.2013 19:39

Вот почему при таком подходе, если быстро дергать мышкой, то драг срывается?
Код AS3:

package
{
        import flash.display.DisplayObject;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
        import flash.geom.Point;
 
        public class Drag extends Sprite
        {
                private var _container:Sprite;
 
                private var _spriteArray:Vector.<Sprite>;
 
                private var _conteinersArray:Vector.<Sprite>;
                private var _distantion:Point;
                private var _target:Sprite;
 
                public function Drag()
                {
                        if (stage) init();
                        else addEventListener(Event.ADDED_TO_STAGE, init);
                }
 
                private function init(event:Event=null):void
                {
                        removeEventListener(Event.ADDED_TO_STAGE, init);
 
                        _conteinersArray = Vector.<Sprite>([]);
 
                        this.addEventListener(MouseEvent.MOUSE_DOWN, this_mouseDownHandler);
                        _container = new Sprite();
                        _container.name = 'con';
                        _conteinersArray.push(_container);
                        super.addChild(_container);
                        var circle:Sprite;
                        _spriteArray = Vector.<Sprite>([]);
 
 
                        for (var i:int = 0; i < 10; i++)
                        {
                                circle = new Sprite();
                                circle.graphics.beginFill(Math.random() * 0xf6f6f6);
                                circle.graphics.drawCircle(Math.random() * stage.stageWidth, Math.random() * stage.stageHeight, 30);
                                circle.graphics.endFill();
                                _spriteArray.push(circle);
                                _container.addChild(_spriteArray[i] as DisplayObject);
                        }
                }
 
                private function this_mouseDownHandler(event:MouseEvent):void
                {
                        if (_conteinersArray.indexOf(event.target > 0))
                        {
                                trace('good');
                                this.addEventListener(MouseEvent.MOUSE_UP, this_mouseUpHandler);
                                this.addEventListener(MouseEvent.MOUSE_MOVE, this_mouseMoveHandler);
                                _target = event.target.parent as Sprite;
                                _distantion = new Point(event.localX, event.localY);
                        }
                }
 
                private function this_mouseUpHandler(event:MouseEvent):void
                {
                        trace('up');
                        this.removeEventListener(MouseEvent.MOUSE_UP, this_mouseUpHandler);
                        this.removeEventListener(MouseEvent.MOUSE_MOVE, this_mouseMoveHandler);
                        event.stopPropagation();
                }
                private function this_mouseMoveHandler(event:MouseEvent):void
                {
                        _target.x =  mouseX - _distantion.x;
                        _target.y = mouseY - _distantion.y;
                        event.updateAfterEvent();
                }
 
        }
 
}


Rivexe 27.09.2013 19:44

Akopalipsis, потом что событие MOUSE_MOVE висит на спрайте, который закрашен кружками, соответственно оно диспачится только когда вы водите над ними.
замените:
Код AS3:

this.addEventListener(MouseEvent.MOUSE_MOVE, this_mouseMoveHandler);

на:
Код AS3:

stage.addEventListener(MouseEvent.MOUSE_MOVE, this_mouseMoveHandler);


Akopalipsis 27.09.2013 20:06

Цитата:

потом что событие MOUSE_MOVE висит на спрайте
Спасибо! Что то недоглядел.
А почему когда мышка выходит за ограничения то обьекты все равно двигаются, хотя слушатель удалён?
Или он не удаляется пока не завершиться его работа?
Код AS3:

private function this_mouseMoveHandler(event:MouseEvent):void 
                {
                        if (mouseX >  this.width)
                        {
                                trace('>');
                                stage.removeEventListener(MouseEvent.MOUSE_MOVE, this_mouseMoveHandler);
                                this.removeEventListener(MouseEvent.MOUSE_DOWN, this_mouseDownHandler);
                        }
                        _target.x =  mouseX - _distantion.x;
                        _target.y = mouseY - _distantion.y;
                        event.updateAfterEvent();
                }


Rivexe 27.09.2013 20:11

Вероятно, потому что вы удаляете слушатель с спрайта, а подписаны на stage
Код AS3:

this.removeEventListener(MouseEvent.MOUSE_MOVE, this_mouseMoveHandler);

надо
Код AS3:

stage.removeEventListener(MouseEvent.MOUSE_MOVE, this_mouseMoveHandler);


Akopalipsis 27.09.2013 20:19

Rivexe я опять внимания не обратил))) Спасибо!
Не знаю на сколько правильно ( очень надеюсь , что правильность прокомментируют ) но работает.
Код AS3:

package 
{
        import flash.display.DisplayObject;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
        import flash.geom.Point;
 
        public class Drag extends Sprite
        {
                private var _container:Sprite;
 
                private var _spriteArray:Vector.<Sprite>;
 
                private var _conteinersArray:Vector.<Sprite>;
 
                private var _distantion:Point;
                private var _target:Sprite;
 
                private var _maxX:int;
                private var _maxY:int;
                private var _minX:int;
                private var _minY:int;
 
                public function Drag()
                {
                        if (stage) init();
                        else addEventListener(Event.ADDED_TO_STAGE, init);
                }
 
                private function init(event:Event=null):void
                {
                        removeEventListener(Event.ADDED_TO_STAGE, init);
 
                        _conteinersArray = Vector.<Sprite>([]);
 
                        this.addEventListener(MouseEvent.MOUSE_DOWN, this_mouseDownHandler);
                        _container = new Sprite();
                        _conteinersArray.push(_container);
                        super.addChild(_container);
                        var circle:Sprite;
                        _spriteArray = Vector.<Sprite>([]);
 
 
                        for (var i:int = 0; i < 10; i++)
                        {
                                circle = new Sprite();
                                circle.graphics.beginFill(Math.random() * 0xf6f6f6);
                                circle.graphics.drawCircle(Math.random() * stage.stageWidth, Math.random() * stage.stageHeight, 30);
                                circle.graphics.endFill();
                                _spriteArray.push(circle);
                                _container.addChild(_spriteArray[i] as DisplayObject);
                        }
 
                        _maxX = this.width;
                        _maxY = this.height;
 
                        _minX = this.width - this.width;
                        _minY = this.height - this.height;
 
                }
 
                private function this_mouseDownHandler(event:MouseEvent):void
                {
                        if (_conteinersArray.indexOf(event.target > 0))
                        {
                                this.addEventListener(MouseEvent.MOUSE_UP, this_mouseUpHandler);
                                stage.addEventListener(MouseEvent.MOUSE_MOVE, this_mouseMoveHandler);
                                _target = event.target.parent as Sprite;
                                _distantion = new Point(event.localX, event.localY);
                        }
                }
 
                private function this_mouseUpHandler(event:MouseEvent):void
                {
                        this.removeEventListener(MouseEvent.MOUSE_UP, this_mouseUpHandler);
                        stage.removeEventListener(MouseEvent.MOUSE_MOVE, this_mouseMoveHandler);
                }
                private function this_mouseMoveHandler(event:MouseEvent):void
                {
                        if (mouseX > _maxX || mouseX < _minX || mouseY > _maxY || mouseY < _minY)
                        {
                                stage.removeEventListener(MouseEvent.MOUSE_MOVE, this_mouseMoveHandler);
                                this.removeEventListener(MouseEvent.MOUSE_UP, this_mouseUpHandler);
                                _target = null;
                                _distantion = null;
                                return;
                        }
                        _target.x =  mouseX - _distantion.x;
                        _target.y = mouseY - _distantion.y;
                        event.updateAfterEvent();
                }
 
        }
 
}


kelod 27.09.2013 20:24

Цитата:

Сообщение от Akopalipsis (Сообщение 1147115)
Rivexe я опять внимания не обратил))) Спасибо!
Не знаю на сколько правильно ( очень надеюсь , что правильность прокомментируют ) но работает.
Код AS3:

package 
{
        import flash.display.DisplayObject;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
        import flash.geom.Point;
 
        public class Drag extends Sprite
        {
                private var _container:Sprite;
 
                private var _spriteArray:Vector.<Sprite>;
 
                private var _conteinersArray:Vector.<Sprite>;
 
                private var _distantion:Point;
                private var _target:Sprite;
 
                private var _maxX:int;
                private var _maxY:int;
                private var _minX:int;
                private var _minY:int;
 
                public function Drag()
                {
                        if (stage) init();
                        else addEventListener(Event.ADDED_TO_STAGE, init);
                }
 
                private function init(event:Event=null):void
                {
                        removeEventListener(Event.ADDED_TO_STAGE, init);
 
                        _conteinersArray = Vector.<Sprite>([]);
 
                        this.addEventListener(MouseEvent.MOUSE_DOWN, this_mouseDownHandler);
                        _container = new Sprite();
                        _conteinersArray.push(_container);
                        super.addChild(_container);
                        var circle:Sprite;
                        _spriteArray = Vector.<Sprite>([]);
 
 
                        for (var i:int = 0; i < 10; i++)
                        {
                                circle = new Sprite();
                                circle.graphics.beginFill(Math.random() * 0xf6f6f6);
                                circle.graphics.drawCircle(Math.random() * stage.stageWidth, Math.random() * stage.stageHeight, 30);
                                circle.graphics.endFill();
                                _spriteArray.push(circle);
                                _container.addChild(_spriteArray[i] as DisplayObject);
                        }
 
                        _maxX = this.width;
                        _maxY = this.height;
 
                        _minX = this.width - this.width;
                        _minY = this.height - this.height;
 
                }
 
                private function this_mouseDownHandler(event:MouseEvent):void
                {
                        if (_conteinersArray.indexOf(event.target > 0))
                        {
                                this.addEventListener(MouseEvent.MOUSE_UP, this_mouseUpHandler);
                                stage.addEventListener(MouseEvent.MOUSE_MOVE, this_mouseMoveHandler);
                                _target = event.target.parent as Sprite;
                                _distantion = new Point(event.localX, event.localY);
                        }
                }
 
                private function this_mouseUpHandler(event:MouseEvent):void
                {
                        this.removeEventListener(MouseEvent.MOUSE_UP, this_mouseUpHandler);
                        stage.removeEventListener(MouseEvent.MOUSE_MOVE, this_mouseMoveHandler);
                }
                private function this_mouseMoveHandler(event:MouseEvent):void
                {
                        if (mouseX > _maxX || mouseX < _minX || mouseY > _maxY || mouseY < _minY)
                        {
                                stage.removeEventListener(MouseEvent.MOUSE_MOVE, this_mouseMoveHandler);
                                this.removeEventListener(MouseEvent.MOUSE_UP, this_mouseUpHandler);
                                _target = null;
                                _distantion = null;
                                return;
                        }
                        _target.x =  mouseX - _distantion.x;
                        _target.y = mouseY - _distantion.y;
                        event.updateAfterEvent();
                }
 
        }
 
}


примерно так и я сделал, разве что переменных столько не объявлял, мне не нравится такое решение, но наверно по другому не как не выйдет, ладно спасибо пусть так и будет

temp 27.09.2013 20:25

Попробуйте еще слушать вот это --
Код AS3:

 
stage.addEventListener(Event.MOUSE_LEAVE,leaveStage);
 
private function leaveStage(e:Event):void
{
    //сработает когда курсор покинет флешку
}

параллельно можно менять булеву переменную - что ложь - если курсор за пределами,
истина если в границах сцены, и действовать в зависимости от этого

Akopalipsis 27.09.2013 20:37

temp Спасибо! я помню, что есть какое то событие, которое за выход за сцену отвечает. Искал его, но в событиях мыши. Жалко, что нет события отвечающего за выход за рамку...


Часовой пояс GMT +4, время: 05:47.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.