|
|
« Предыдущая тема | Следующая тема » |
Опции темы | Опции просмотра |
|
|
|||||
Регистрация: Oct 2010
Сообщений: 85
|
множественное выделение объектов и взаимодействие[multiple selection]
Добрый день,
Есть некий трек-лист, наподобие обычного компонента List. По нему может перемещаться определенное кол-во объектов. Объекты перемещаются вверх, вниз. Вот никак не могу понять, как реализовать корректное перемещение этих объектов, если выделен не один объект, а несколько. Я, понимаю, что сперва нужно запомнить изначальное положение объектов и потом прибавлять к этим координатам обновленные, но, блин, что-то я не то делаю, получается не правильно. Пример прилагаю. Для выделения нескольких объектов, зажмите ctrl и кликайте на объекты, не отпуская ctrl тяните вниз||вверх. 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; } } |
|
|||||
Чтобы корректно перетаскивать один объект, вам достаточно запомнить координаты этого объекта (offset) при нажатии мыши. А при движении мыши, устанавливать объект в координаты мыши и отнимать ранее зафиксированные координаты (offset). Так сделайте это для каждого вашего объекта. Создайте массив, в который будете помещать смещение каждого объекта, а потом используйте эти данные.
Во флеше ниже, вы можете выделять объекты или группировать их с помощью ctrl. Комментарии в коде помогут вам понять, что к чему (по идее). Только в браузере ctrl не срабатывает (почему не знаю), по этому придётся открыть флешку локально. Main 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); } } } 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(); } } } Последний раз редактировалось samana; 06.04.2014 в 22:38. |
|
|||||
Banned
[+4 24.02.14]
[+4 07.11.13] [+ 13.03.14] Регистрация: Mar 2013
Сообщений: 1,864
|
Цитата:
|
|
|||||
У меня в опере работает Ctrl+CLICK. Правда при попытке перетаскивания у меня с нажатого снимается выделение. Выделяйте и снимайте выделение при CLICK событии, а не на MOUSE_DOWN.
__________________
There is no thing in this world that is not simple. |
|
|||||
Это была моя логическая ошибка, которую я поправил. Свой пост выше обновил, немного упростив его.
|
|
|||||
Регистрация: Oct 2010
Сообщений: 85
|
samana, большое спасибо за решение, целый урок вышел. Очень помогли мне.
|
|
|||||
строго говоря, такие перетурбации нужно делать с dataProvider (или, например с коллекцией данных для листа)
|
Часовой пояс GMT +4, время: 14:54. |
|
« Предыдущая тема | Следующая тема » |
Опции темы | |
Опции просмотра | |
|
|