Пользователю можно предоставить возможность перемещать экранные объекты с помощью мыши, используя два разных приема в ActionScript. В обоих случаях применяется два события мыши. Когда кнопка мыши нажата, объекту передается инструкция следовать за курсором, а когда она отпущена, передается инструкция о прекращении следования за курсором.
Примечание.
Flash Player 11.3 и AIR 3.3 или более поздних версий: можно также использовать событие MouseEvent.RELEASE_OUTSIDE на тот случай, если пользователь отпускает кнопку мыши за границами содержащего объекта Sprite.
Первый прием предполагает использование метода
startDrag()
. Он проще, но имеет больше ограничений. При нажатии кнопки мыши вызывается метод
startDrag()
экранного объекта, который необходимо перетащить. Когда кнопка отпущена, вызывается метод
stopDrag()
. Класс Sprite определяет эти две функции, поэтому перемещаемый объект должен быть экземпляром класса Sprite или одного из его подклассов.
// This code creates a mouse drag interaction using the startDrag()
// technique.
// square is a MovieClip or Sprite instance).
import flash.events.MouseEvent;
// This function is called when the mouse button is pressed.
function startDragging(event:MouseEvent):void
{
square.startDrag();
}
// This function is called when the mouse button is released.
function stopDragging(event:MouseEvent):void
{
square.stopDrag();
}
square.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
square.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
У этого метода есть одно довольно существенное ограничение: с помощью метода
startDrag()
можно перетаскивать только один объект за раз. Если перетаскивается один экранный объект, а метод
startDrag()
вызывается для другого экранного объекта, первый экранный объект сразу же перестает следовать за мышью. Например, если функция
startDragging()
изменяется так, как здесь показано, будет перетаскиваться только объект
circle
, несмотря на вызов метода
square.startDrag()
:
function startDragging(event:MouseEvent):void
{
square.startDrag();
circle.startDrag();
}
Из-за того, что одновременно с помощью метода
startDrag()
можно перетащить только один объект, метод
stopDrag()
можно вызвать по отношению к любому экранному объекту. При этом перетаскивание любого другого объекта останавливается.
Если вам необходимо перетащить более одного экранного объекта или избежать возможных конфликтов, которые возникают, когда метод
startDrag()
используется более чем одним объектом, используйте технику следования за мышью, чтобы добиться эффекта перетаскивания. В случае данной техники когда нажимается кнопка, функция регистрируется в качестве прослушивателя события
mouseMove
рабочей области. Эта функция, которая затем вызывается при каждом движении мыши, приводит к тому, что перетаскиваемый объект переходит к точке расположения курсора с координатами x и y. После отпускания кнопки мыши функция перестает восприниматься как прослушиватель. Это означает, что она больше не вызывается при перемещениях мыши, и объект перестает следовать за курсором. Ниже приведен код, иллюстрирующий данный метод:
// This code moves display objects using the mouse-following
// technique.
// circle is a DisplayObject (e.g. a MovieClip or Sprite instance).
import flash.events.MouseEvent;
var offsetX:Number;
var offsetY:Number;
// This function is called when the mouse button is pressed.
function startDragging(event:MouseEvent):void
{
// Record the difference (offset) between where
// the cursor was when the mouse button was pressed and the x, y
// coordinate of the circle when the mouse button was pressed.
offsetX = event.stageX - circle.x;
offsetY = event.stageY - circle.y;
// tell Flash Player to start listening for the mouseMove event
stage.addEventListener(MouseEvent.MOUSE_MOVE, dragCircle);
}
// This function is called when the mouse button is released.
function stopDragging(event:MouseEvent):void
{
// Tell Flash Player to stop listening for the mouseMove event.
stage.removeEventListener(MouseEvent.MOUSE_MOVE, dragCircle);
}
// This function is called every time the mouse moves,
// as long as the mouse button is pressed down.
function dragCircle(event:MouseEvent):void
{
// Move the circle to the location of the cursor, maintaining
// the offset between the cursor's location and the
// location of the dragged object.
circle.x = event.stageX - offsetX;
circle.y = event.stageY - offsetY;
// Instruct Flash Player to refresh the screen after this event.
event.updateAfterEvent();
}
circle.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
circle.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
Часто требуется, чтобы экранный объект не просто следовал за курсором мыши, но и оставался на переднем плане во время перетаскивания. При этом создается впечатление, что он плавает поверх всех остальных объектов. Предположим, что имеется два объекта, круг и квадрат, которые можно перетаскивать с помощью мыши. Если круг находится под квадратом в списке отображения, и вы щелкнете и перетащите его, чтобы курсор оказался над квадратом, вам покажется, что круг зашел за квадрат. Это вызовет нарушение иллюзии. Вместо этого можно сделать так, что при нажатии круга он переместится на вершину списка отображения, и при этом всегда будет находиться над остальным содержимым.
Следующий код (адаптированный из предыдущего примера) позволяет перемещать с помощью мыши два экранных объекта, круг и квадрат. Каждый раз, когда на любой из них наводится курсор и нажимается кнопка мыши, соответствующий элемент перемещается в верхнюю часть списка отображения рабочей области и из-за этого при перетаскивании он всегда находится сверху. (Новый код или измененный код из предыдущего примера выделен полужирным.)
// This code creates a drag-and-drop interaction using the mouse-following
// technique.
// circle and square are DisplayObjects (e.g. MovieClip or Sprite
// instances).
import flash.display.DisplayObject;
import flash.events.MouseEvent;
var offsetX:Number;
var offsetY:Number;
var draggedObject:DisplayObject;
// This function is called when the mouse button is pressed.
function startDragging(event:MouseEvent):void
{
// remember which object is being dragged
draggedObject = DisplayObject(event.target);
// Record the difference (offset) between where the cursor was when
// the mouse button was pressed and the x, y coordinate of the
// dragged object when the mouse button was pressed.
offsetX = event.stageX - draggedObject.x;
offsetY = event.stageY - draggedObject.y;
// move the selected object to the top of the display list
stage.addChild(draggedObject);
// Tell Flash Player to start listening for the mouseMove event.
stage.addEventListener(MouseEvent.MOUSE_MOVE, dragObject);
}
// This function is called when the mouse button is released.
function stopDragging(event:MouseEvent):void
{
// Tell Flash Player to stop listening for the mouseMove event.
stage.removeEventListener(MouseEvent.MOUSE_MOVE, dragObject);
}
// This function is called every time the mouse moves,
// as long as the mouse button is pressed down.
function dragObject(event:MouseEvent):void
{
// Move the dragged object to the location of the cursor, maintaining
// the offset between the cursor's location and the location
// of the dragged object.
draggedObject.x = event.stageX - offsetX;
draggedObject.y = event.stageY - offsetY;
// Instruct Flash Player to refresh the screen after this event.
event.updateAfterEvent();
}
circle.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
circle.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
square.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
square.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
Чтобы расширить сферу применения этого эффекта (например, для игры, в которой фишки или карты перемещаются среди стопок, можно добавить перетаскиваемый объект в список отображения рабочей области, когда его «поднимают», а затем добавить его в другой список отображения (например, «стопку», в которую его следует уронить) при отпускании кнопки мыши.
И, наконец, чтобы усилить этот эффект, можно применить фильтр тени к экранному объекту при нажатии (когда вы начнете его перетаскивать) и удалить тень при отпускании объекта. Сведения об использовании фильтра тени и других фильтров экранного объекта в ActionScript см. в разделе «
Фильтрация экранных объектов
».