Yes, i just want to let the user move an image arround its container canvas. Flex does not provide you a direct API for that. You need to fall back to Drag & Drop API. Right-clic below to see source code

You need JavaScript enabled!

Ci-dessus, vous pouvez déplacer les images qui réprésentent les pièces d'échecs : un échec et mat évident en un coup... Pour ce qui est du code Flex, commençons par le début du Drag & Drop.

Drag & Drop with Flex DnD-enabled controls

Ok, prenons les choses depuis le départ. Flex offre un bon support de Drag & Drop, ce qui permet une mise en oeuvre simple pour les composants tels List, DataGrid et Tree.

You need JavaScript enabled!
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal"> 
  <mx:Array id="fruits">['Orange', 'Apple', 'Blackberry', 'Cranberry', 'Banana']</mx:Array>
  <mx:Panel title="Available" width="50%" height="100%" >
    <mx:List dragEnabled="true" dataProvider="{fruits}" width="100%" height="100%" />
  </mx:Panel>
  <mx:Panel title="My selection" width="50%" height="100%" >
    <mx:List dropEnabled="true" width="100%" height="100%" />
  </mx:Panel>
</mx:Application>

Bref il suffit d'activer les propriétés dragEnabled et dropEnabled.

Moving an image

Flex DnD API is straitforward for those DnD-enabled controls. But in order to move arround an image, a DragManager will need to be used.

Dragging an image

Nous allons voir comment, dès qu'on sort du cadre des composants Dnd-enabled, il faut utiliser explicitement le DragManager [1]. Pour qu'une image soit éligible au Drag, on a typiquement, ceci.

<mx:Image mouseDown="dragging(event);" />
private function dragging(event:MouseEvent):void {                
  var dragInitiator:Image = event.currentTarget as Image;
  var ds:DragSource = new DragSource();
  ds.addData(dragInitiator, "img");
  DragManager.doDrag(dragInitiator, ds, event);
}

A partir de là, on peut effectivement déplacer l'image en maintenant le bouton gauche de la souris. Mais le rendu n'est pas terrible, car au moment du déplacement, notre image cible est alors simplement matérialisé par un rectangle. On peut vérifier avec l'extrait suivant :

Dragging with custom feedback proxy

Mais on peut préciser au DragManager une image à utiliser pendant le déplacement et qui sera affichée comme feedback pendant le drag. On peut valoriser le 4-ième paramètres (optionnel) de la méthode doDrag().

private function dragging(event:MouseEvent):void {                
  var dragInitiator:Image = event.currentTarget as Image;
  var ds:DragSource = new DragSource();
  ds.addData(dragInitiator, "img");
  var imageProxy:Image = new Image();
  imageProxy.source = event.currentTarget.source;
  imageProxy.width= dragInitiator.width;
  imageProxy.height= dragInitiator.height;
  DragManager.doDrag(dragInitiator, ds, event, imageProxy);
}

Et là, autant prendre l'image sur laquelle on veut précisément agir: oui, enfin..., on prendra une copie pour que ca marche.

Dropping

Reste à finaliser le déplacement de notre image, pour cela il faut que notre conteneur, ici un Canvas, accepte le Drop. Pour cela, on peut se contenter de ceci :

<mx:Canvas dragEnter="DragManager.acceptDragDrop( event.currentTarget as Canvas);"
  dragDrop="dragDropHandler(event);" />
private function dragDropHandler(event:DragEvent):void {
  var image:Image = event.dragInitiator as Image;
  var container:Canvas = event.currentTarget as Canvas;
  image.x = container.mouseX; 
  image.y = container.mouseY;
}

Là, on y est presque. Sauf que vous l'avez vu quand on lâche l'image, elle ne se pose pas à l'endroit naturelle. En fait c'est un peu se qui se passe aussi dans l'exemple de DnD d'image à la fin du billet de Xebia [2]. Le problème le voici : quand on initialise le Drag, on clique n'importe où dans l'image et quand on relâche la souris, le coin supérieur gauche de l'image prend la position de la souris. Mais pour compenser, il suffit de compléter comme suit :

<mx:Canvas dragEnter="DragManager.acceptDragDrop( event.currentTarget as Canvas);"
        mouseDown="recordPosition(event)"
        dragDrop="dragDropHandler(event);" />
private function recordPosition(event:MouseEvent):void {
  fromX = event.localX;
  fromY = event.localY;
}
private function dragDropHandler(event:DragEvent):void {
  var image:Image = event.dragInitiator as Image;
  var container:Canvas = event.currentTarget as Canvas;
  image.x = container.mouseX - fromX; 
  image.y = container.mouseY - fromY;
}

Ouf, là on y est!

Comme quoi le Drag&Drop est immédiat en Flex pour les composants List, DataGrid, Tree : activer les propriétés dragEnable et dropEnabled.

Par contre pour déplacer une image, il n'y a pas d'API direct et il faut mettre en oeuvre un Drag & Drop avec DragManager et là ce présent tutorial peut guider pour les quelques 15 lignes de code nécessaires.

Pour le code source : un simple clic droit sur l'échiquier en début de billet.