Você pode permitir que um usuário movimente objetos de exibição com o mouse, utilizando duas técnicas diferentes no ActionScript. Em ambos os casos, dois eventos de mouse são usados: quando o botão do mouse é pressionado, o objeto é acionado para seguir o cursor do mouse e, quando é solto, o objeto deve parar de segui-lo.
Nota:
O Flash Player 11.3 e superior, AIR 3.3 e superior: você também pode usar o evento MouseEvent.RELEASE_OUTSIDE para cobrir o caso de um usuário liberando o botão fora dos limites da entidade gráfica continente.
A primeira técnica, usando o método
startDrag()
, é mais simples, porém mais limitada. Quando o botão do mouse é pressionado, o método
startDrag()
do objeto de exibição a ser arrastado é chamado. Quando o botão do mouse é solto, o método
stopDrag()
é chamado. A classe Sprite define essas duas funções. Portanto, o objeto movimentado deve ser um Sprite ou uma de suas subclasses.
// 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);
Essa técnica tem uma limitação bem significativa: somente um item por vez pode ser arrastado com
startDrag()
. Se um objeto de exibição estiver sendo arrastado e o método
startDrag()
for chamado em outro objeto de exibição, o primeiro objeto deixará de seguir o mouse imediatamente. Por exemplo, se a função
startDragging()
for alterada conforme mostrado aqui, somente o objeto
circle
será arrastado, apesar da chamada do método
square.startDrag()
:
function startDragging(event:MouseEvent):void
{
square.startDrag();
circle.startDrag();
}
Como apenas um objeto pode ser arrastado por vez com
startDrag()
, o método
stopDrag()
pode ser chamado em qualquer objeto de exibição e para sempre que o objeto está sendo arrastado.
Se precisar arrastar mais de um objeto de exibição ou para evitar a possibilidade de conflitos quando houver mais de um objeto que provavelmente use
startDrag()
, é melhor usar a técnica de acompanhamento do mouse para criar o efeito de desenho. Com essa técnica, quando o botão do mouse é pressionado, uma função é inscrita como ouvinte no evento
mouseMove
do palco. Essa função, que é chamada sempre que o mouse se move, faz com que o objeto arrastado passe para a coordenada x, y do mouse. Assim que o botão do mouse é solto, a função deixa de ser ouvinte, ou seja, não será mais chamada quando o mouse se movimentar, e o objeto para de acompanhar o cursor do mouse. Veja um código que demonstra essa técnica:
// 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);
Além de fazer com que um objeto de exibição acompanhe o cursor do mouse, muitas vezes é desejável mover o objeto arrastado até a frente da exibição para que apareça flutuando acima de todos os outros objetos. Por exemplo, suponha que você tenha dois objetos, um círculo e um quadrado, que possam ser movimentados com o mouse. Se o círculo ficar abaixo do quadrado na lista de exibição e você clicar e arrastar o círculo para que o cursor fique por cima do quadrado, irá parecer que o círculo desliza ao lado do quadrado, quebrando a ilusão de arrastar e soltar. Em vez disso, você pode definir que, quando for clicado, o círculo deve se mover para cima da lista de exibição e, assim, sempre aparecer em cima de qualquer outro conteúdo.
O código a seguir (adaptado do exemplo anterior) permite que dois objetos de exibição, um círculo e um quadrado, sejam movimentados com o mouse. Sempre que o botão do mouse é pressionado em um deles, esse item é movido para a parte superior da lista de exibição do palco para que o item arrastado sempre apareça por cima. (O código novo ou alterado com relação à listagem anterior é exibido em negrito.)
// 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);
Para estender esse efeito ainda mais, como para um jogo onde pinos ou cartas são movidos entre pilhas, você pode adicionar o objeto arrastado à lista de exibição do palco quando for “tirado” e adicioná-lo a outra lista de exibição (como a “pilha” onde é solto) quando o botão do mouse for liberado.
Finalmente, para aprimorar o efeito, você poderia aplicar um filtro de sombra projetada no objeto de exibição quando for clicado (quando começar a ser arrastado) e remover a sombra projetada quando o objeto for solto. Para obter detalhes sobre como usar o filtro de sombra projetada e outros filtros de objeto de exibição no ActionScript, consulte
Filtro de objetos de exibição
.