Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   множественное выделение объектов и взаимодействие[multiple selection] (http://www.flasher.ru/forum/showthread.php?t=207289)

BornTOFree 06.04.2014 16:32

множественное выделение объектов и взаимодействие[multiple selection]
 
Вложений: 2
Добрый день,

Есть некий трек-лист, наподобие обычного компонента List. По нему может перемещаться определенное кол-во объектов. Объекты перемещаются вверх, вниз. Вот никак не могу понять, как реализовать корректное перемещение этих объектов, если выделен не один объект, а несколько.

Я, понимаю, что сперва нужно запомнить изначальное положение объектов и потом прибавлять к этим координатам обновленные, но, блин, что-то я не то делаю, получается не правильно.


Пример прилагаю.
Для выделения нескольких объектов, зажмите ctrl и кликайте на объекты, не отпуская ctrl тяните вниз||вверх.
test.swf   (2.3 Кб)


Код AS3:

var row:MovieClip;
var item:MovieClip;
 
var itemContainer:Sprite = new Sprite();
 
var multiSelect:Boolean;
 
var currentTarget:DisplayObject;
var currentRowId:int;
var arrRow:Array = new Array();
var arrItem:Array = new Array();
var arrSelectedItem:Array = new Array();
var arrPosItem:Array = new Array();
 
 
stage.addEventListener(KeyboardEvent.KEY_DOWN, ctrlDown);
stage.addEventListener(KeyboardEvent.KEY_UP, ctrlUp);
 
stage.addChild(itemContainer);
 
for(var i:int = 0; i < 5; i++) {
        row = new Row();
        addChild(row);
        arrRow.push(row);
        row.addEventListener(MouseEvent.MOUSE_MOVE, onMoveRow);
        row.y = row.height*i+1;
}
for(var j:int = 0; j < 2; j++) {
        item = new Item();
        itemContainer.addChild(item);
        arrItem.push(item);
        item.addEventListener(MouseEvent.MOUSE_DOWN, onDownItem);
        item.x = (item.width + 50)*j;
}
 
function onMoveRow(e:MouseEvent):void {
        currentTarget = e.currentTarget as DisplayObject;
        currentRowId = arrRow.indexOf(currentTarget);
        trace(currentRowId);
 
}
function unSelect():void {
 
        for (var i:int = 0; i < arrItem.length; i++ ) {
                arrItem[i].gotoAndStop(1);
 
        }
}
 
function onDownItem(e:MouseEvent):void {
 
        if (!multiSelect) {
                unSelect();
                arrSelectedItem = [];
                arrPosItem = [];
                if (arrSelectedItem.length < 1) arrSelectedItem.push(e.currentTarget), arrPosItem.push(e.currentTarget.y);
        }else {
 
                arrSelectedItem.push(e.currentTarget);
                arrPosItem.push(e.currentTarget.y);
        }
 
        e.currentTarget.gotoAndStop(2);
 
        itemContainer.mouseChildren = false;
        itemContainer.mouseEnabled = false;
 
        stage.addEventListener(MouseEvent.MOUSE_MOVE, bgOnMove);
        stage.addEventListener(MouseEvent.MOUSE_UP, bgOnUp);
 
}
 
function bgOnUp(e:MouseEvent):void {
 
        itemContainer.mouseChildren = true;
        itemContainer.mouseEnabled = true;
 
        stage.removeEventListener(MouseEvent.MOUSE_MOVE, bgOnMove);
        stage.removeEventListener(MouseEvent.MOUSE_UP, bgOnUp);
 
}
 
function bgOnMove(e:Event):void {
 
        for (var i:int = 0; i < arrSelectedItem.length; i++) {
                var item:DisplayObject = arrSelectedItem[i];
                item.y = arrRow[currentRowId].y;
        }
}
 
 
 
 
 
 
function ctrlDown(e:KeyboardEvent):void {
        if( e.keyCode == Keyboard.CONTROL ){
                multiSelect = true;
        }
 
}
 
function ctrlUp(e:KeyboardEvent):void {
        if( e.keyCode == Keyboard.CONTROL ){
                multiSelect = false;
        }
}


samana 06.04.2014 19:31

Вложений: 2
Чтобы корректно перетаскивать один объект, вам достаточно запомнить координаты этого объекта (offset) при нажатии мыши. А при движении мыши, устанавливать объект в координаты мыши и отнимать ранее зафиксированные координаты (offset). Так сделайте это для каждого вашего объекта. Создайте массив, в который будете помещать смещение каждого объекта, а потом используйте эти данные.
Во флеше ниже, вы можете выделять объекты или группировать их с помощью ctrl.
Комментарии в коде помогут вам понять, что к чему (по идее).
Только в браузере ctrl не срабатывает (почему не знаю), по этому придётся открыть флешку локально.
NewProjectKey.swf   (2.2 Кб)


Main
Код AS3:

package 
{
        import flash.display.InteractiveObject;
        import flash.display.Sprite;
        import flash.display.Stage;
        import flash.events.Event;
        import flash.events.KeyboardEvent;
        import flash.events.MouseEvent;
        import flash.geom.Point;
 
        /**
        * ...
        * @author samana
        */

        public class Main extends Sprite
        {
                //массив с текущими выделенными объектами
                private var selectionList:Vector.<Item> = new Vector.<Item>();
                //массив с данными о смещении каждого объекта относительно мыши
                private var offsets:Vector.<Point> = new Vector.<Point>();
 
                public function Main():void
                {
                        //создаю объекты на сцене
                        createItems();
                        //подписыаю сцену на нажатие мыши, чтобы убирать выделение на объектах если оно было.
                        stage.addEventListener(MouseEvent.MOUSE_DOWN, stage_mouseDown);
 
                        //рисую на сцене полоски просто для красоты
                        graphics.lineStyle(0.5,0xBFBFBD);
                        for (var i:int = 0; i < 20; i++)
                        {
                                graphics.moveTo(0, 25 * i);
                                graphics.lineTo(800, 25 * i);
                        }
 
                }
                //если клик был по пустом месту на сцене, то убираем выделение с объектов
                //и опустошаем массив с выделенными объектами.
                private function stage_mouseDown(e:MouseEvent):void
                {
                        if (e.target is Stage)
                        {
                                for (var i:int = 0; i < selectionList.length; i++)
                                {
                                        selectionList[i].selectOff();
                                }
                                selectionList.length = 0;
                        }
                }
 
                private function createItems():void
                {
                        //создаю объекты
                        for (var i:int = 0; i < 20; i++)
                        {
                                var item:Item = new Item();
                                item.x = i * 30;
                                item.y = i * 25;
 
                                //добавляю объект на сцену
                                addChild(item);
 
                                //-------------------------
                                //каждый объект подписываю на нажатие мыши
                                item.addEventListener(MouseEvent.MOUSE_DOWN, item_mouseDown);
                        }
                }
 
 
 
                //при нажатии по item
                private function item_mouseDown(e:MouseEvent):void
                {
                        //текущий item на который нажали мышкой
                        var item:Item = e.currentTarget as Item;
 
                        //если во время нажатия мыши был зажат контрол то
                        if (e.ctrlKey)
                        {
                                //если текущий item ещё не находиться в массиве выделенных объектов, то
                                //помещаем его в этот массив и подсвечиваем объект (для наглядности)
                                var ind:int = selectionList.indexOf(item);
                                if (ind == -1)
                                {
                                        selectionList.push(item);
                                        item.selectOn();
                                }
                                //если же текущий item уже есть в массиве для выделенных объектов, то
                                //удаляем его из этого массива и убераем подсветку
                                else
                                {
                                        selectionList.splice(ind, 1);
                                        item.selectOff();
                                }
                        }
                        //если во время нажатия мыши контрол не зажат
                        //и текущий объект не находится в массиве, то опустошаем массив
                        //и заносим в него только один, последний объект, на котором была зажата мышь
                        else
                        {
                                if (selectionList.indexOf(item)== -1)
                                {
                                        for (var i:int = 0; i < selectionList.length; i++)
                                        {
                                                selectionList[i].selectOff();
                                        }
                                        selectionList.length = 0;
                                        selectionList[0] = item;
                                        item.selectOn();
                                }
                        }
 
                        //и пробегаемся по массиву с выделенными объектами (не важно сколько их)
                        //и каждый запонимает текущее смещение каждого item относительно мыши
                        offsets.length = 0;
                        for (var j:int = 0; j < selectionList.length; j++)
                        {
                                item = selectionList[j];
                                addChild(item);
                                offsets[j] = new Point(mouseX-item.x, mouseY-item.y);
                        }
 
                        //пришло время подвисать сцену на движение мыши
                        stage.addEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMove);
                        //подписываю сцену на отжатие мыши, чтобы удалить MOUSE_MOVE
                        stage.addEventListener(MouseEvent.MOUSE_UP, stage_mouseUp);
                }
 
                //при движении мыши
                private function stage_mouseMove(e:MouseEvent):void
                {
                        var item:Item;
 
                        //пробегаемся по массиву с выделенными объектами и
                        //устанавливаем их в координаты мыши и вычитаем смещение, которое запоминали
                        //при клике по объектам.
                        for (var i:int = 0; i < selectionList.length; i++)
                        {
                                item = selectionList[i];
 
                                item.x = mouseX - offsets[i].x;
                                item.y = 25 * int((mouseY - offsets[i].y) / 25);
                        }
                }
 
                //при отжатии мыши по сцене, отписываю сцену от события движения мыши,
                //чтобы объекты перестали двигаться.
                private function stage_mouseUp(e:MouseEvent):void
                {
                        stage.removeEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMove);
                }
 
        }
 
}

Item
Код AS3:

package  
{
        import flash.display.Sprite;
        import flash.geom.Point;
 
        /**
        * ...
        * @author samana
        */

        public class Item extends Sprite
        {
 
                public function Item()
                {
                        selectOff();
                }
 
                public function selectOn():void
                {
                        graphics.clear();
                        graphics.beginFill(0x99EC00);
                        graphics.lineStyle(1);
                        graphics.drawRect(0, 0, 70, 25);
                        graphics.endFill();
                }
 
                public function selectOff():void
                {
                        graphics.clear();
                        graphics.beginFill(0x1DA3CF);
                        graphics.lineStyle(1);
                        graphics.drawRect(0, 0, 70, 25);
                        graphics.endFill();
                }
 
        }
 
}


Akopalipsis 06.04.2014 20:26

Цитата:

Только в браузере ctrl не срабатывает (почему не знаю), по этому придётся открыть флешку локально
В IE работает.

samana 06.04.2014 20:31

Цитата:

Сообщение от Akopalipsis (Сообщение 1163069)
В IE работает.

О, это хорошо!

ZackMercury 06.04.2014 21:30

У меня в опере работает Ctrl+CLICK. Правда при попытке перетаскивания у меня с нажатого снимается выделение. Выделяйте и снимайте выделение при CLICK событии, а не на MOUSE_DOWN.

samana 06.04.2014 22:40

Цитата:

Сообщение от SuriTheAngel (Сообщение 1163073)
Правда при попытке перетаскивания у меня с нажатого снимается выделение.

Это была моя логическая ошибка, которую я поправил. Свой пост выше обновил, немного упростив его.

BornTOFree 07.04.2014 18:53

samana, большое спасибо за решение, целый урок вышел. Очень помогли мне.

djyamato 07.04.2014 22:23

строго говоря, такие перетурбации нужно делать с dataProvider (или, например с коллекцией данных для листа)


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

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