Apache Adobe Flex TutorialTutoriaux Adobe Flex & AIR en Français

10fév/094

Flex Drag And Drop – Opérations Drag And Drop personnalisées en ActionScript

Les fonctionnalités de Drag And Drop de base fonctionneront dans la plupart des cas. Cependant, il y a de nombreux cas d'utilisation dans lesquels vous voudrez employer les fonctionnalités de drag n drop non supportées par les capacités du framework de base. Dans ces cas, vous devrez créer des éléments drag and drop personnalisés en ActionScript 3.

Vous pouvez créer des éléments de drag and drop en utilisant les évènements présentés dans ces articles:

Flex Drag And Drop - Les évènements utilisables pour le Drag And Drop

Vous devez utiliser ces events en conjonction avec le DragManager mx.managers.DragManager. La classe DragManager a plusieurs méthodes static que vous pourrez utiliser.

La méthode doDrag() permet de commencer une opération de Drag And Drop. La méthode doDrag() requiert que vous lui spécifiez les paramètres suivants:

  • Le Drag Initiator (celui d'où par le D&D)
  • Un objet DragSource spécifiant la donnée à copier depuis l'initiator
  • L'évènement souris (MouseEvent) utilisé pour commencer l'opération de drag

En plus de cela, dans la plupart des cas, vous devrez passer une référence vers un objet à utiliser en tant que drag proxy (l'élément qui est affiché lors du déplacement).

Avant de voir le fonctionnement de doDrag(), je vais expliquer le fonctionnement de DragSource en détail. L'objet DragSource que vous passez à la méthode doDrag() sera passé ensuite aux event handler (les fonctions qui gèrent l'arrivée d'un évènement) pour tous les évènements de drag. Cet objet contient la donnée que vous voudrez utiliser quand vous copiez, déplacez ou comparez. Cela veut dire que vous allez y mettre toute la donnée que vous voulez passer au long de l'opération. Les objets DragSource permettent de sauvegarder de nombreux groupes de donnée, chacun avec une clé unique (String) appelée un "format". Vous pouvez utiliser la méthode addData() pour ajouter de la data à un objet DragSource. Le premier paramètre est la donnée à sauvegarder, et le second paramètre est le format, qui est une chaîne (String) arbitraire:

var dragSource:DragSource = new DragSource();
dragSource.addData(initiator.dataProvider.getItemAt(index), "item");

La classe DragManager dicte aussi le comportement de l'image drag proxy que l'utilisateur bouge au dessus de la zone de drop et quand l'utilisateur drop l'objet. Normalement, le proxy indique qu'il ne peut être relâché en affichant un petit cercle rouge avec un  X blanc. Vous pouvez supprimer cet icone en appellant la méthode static DragManager.acceptDragDrop() et en lui passant la référence vers la zone de drop sur laquelle vous voulez autoriser le drop.

Typiquement, vous allez  appeler cette méthode en réponse à un évènement dragEnter.

L'exemple suivant montre comment créer une opération de drag and drop personnalisée. Cette simple application utilise une colonne de canvas colorés et une grille de canvas avec les même couleurs. Les Canvas de la colonne sont draggable. Quand un utilisateur relâche un Canvas sur un autre de la même couleur dans la grille, le canvas sera supprimé de la colonne, et le canvas dans la grille baissera d'opacité:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="srcview/index.html">
	<mx:Script>
		<![CDATA[
			import mx.events.DragEvent;
			import mx.managers.DragManager;
			import mx.containers.Canvas;
			import mx.core.DragSource;
			private function beginDragAndDrop(event:MouseEvent):void{
				var canvas:Canvas = Canvas(event.currentTarget);
				var dragSource:DragSource = new DragSource;
				var color:uint = canvas.getStyle("backgroundColor");
				dragSource.addData(color, "backgroundColor");
				var proxy:Canvas = new Canvas;
				proxy.width = 50;
				proxy.height = 50;
				proxy.setStyle("backgroundColor", color);
				DragManager.doDrag(canvas, dragSource, event, proxy);
			}

			private function dragEnterHandler(event:DragEvent):void{
				var target:Canvas = Canvas(event.currentTarget);
				var initiator:Canvas = Canvas(event.dragInitiator);
				if (matches(target, initiator)){
					DragManager.acceptDragDrop(target);
				}
			}

			private function dragDropHandler(event:DragEvent):void{
				var target:Canvas = Canvas(event.currentTarget);
				var initiator:Canvas = Canvas(event.dragInitiator);
				if (matches(target, initiator)){
					vbox.removeChild(initiator);
					target.alpha = .25;
				}
			}

			private function matches(a:Canvas, b:Canvas):Boolean{
				return a.getStyle("backgroundColor") == b.getStyle("backgroundColor");
			}
		]]>
	</mx:Script>
	<mx:HBox width="100%">
		<mx:VBox id="vbox" height="100%">
			<mx:Canvas width="50" height="50" backgroundColor="#00FF80"
			mouseDown="beginDragAndDrop(event)"/>
			<mx:Canvas width="50" height="50" backgroundColor="#FF8040"
			mouseDown="beginDragAndDrop(event)"/>
			<mx:Canvas width="50" height="50" backgroundColor="#8000FF"
			mouseDown="beginDragAndDrop(event)"/>
			<mx:Canvas width="50" height="50" backgroundColor="#FFFF80"
			mouseDown="beginDragAndDrop(event)"/>
		</mx:VBox>
		<mx:VRule height="213"/>
		<mx:Grid>
			<mx:GridRow width="100%" height="100%">
				<mx:GridItem width="100%" height="100%">
					<mx:Canvas width="50" height="50" backgroundColor="#00FF80"
				dragEnter="dragEnterHandler(event)" dragDrop="dragDropHandler(event)"/>
				</mx:GridItem>
				<mx:GridItem width="100%" height="100%">
					<mx:Canvas width="50" height="50" backgroundColor="#FF8040"
				dragEnter="dragEnterHandler(event)" dragDrop="dragDropHandler(event)"/>
				</mx:GridItem>
			</mx:GridRow>
			<mx:GridRow width="100%" height="100%">
				<mx:GridItem width="100%" height="100%">
					<mx:Canvas width="50" height="50" backgroundColor="#8000FF"
				dragEnter="dragEnterHandler(event)" dragDrop="dragDropHandler(event)"/>
				</mx:GridItem>
				<mx:GridItem width="100%" height="100%">
					<mx:Canvas width="50" height="50" backgroundColor="#FFFF80"
				dragEnter="dragEnterHandler(event)" dragDrop="dragDropHandler(event)"/>
				</mx:GridItem>
			</mx:GridRow>
		</mx:Grid>
	</mx:HBox>
</mx:Application>

Flex Source Code Download: Télécharger le code source complet de l'application

This movie requires Flash Player 11

Articles similaires

Commentaires (4) Trackbacks (0)
  1. Merci pour ce tutorial,

    J'ai une question, depuis plusieurs jours je suis confronte a un probleme et je ne trouve malheureusement pas la solution.

    J'ai un canva qui contient un certain nombre d'objets.
    J'ai pu ajouter la fonctionnalite drag & drop qui fonctionne bien.
    Avec mon implementation, lorsque l'on deplace l'objet, il se positionne de facon a ce que son coin haut gauche ait les memes coordonnes que la souris.

    Je souhaiterais plutot qu'il se positionne exactement dans la position ou il est juste avant que je relache la souris.

    Mon code est le suivant:

    MXML:
    1. private function dragDropHandler(event:DragEvent):void {
    2.                 Desk(event.dragInitiator).x = event.localX;
    3.                 Desk(event.dragInitiator).y = event.localY;
    4.  
    5.         }
    6.     private function beginDragAndDrop(event:MouseEvent):void{
    7.            
    8.         var dragInitiator:Desk=Desk(event.target);
    9.             var ds:DragSource = new DragSource();
    10.             ds.addData(dragInitiator, "desk");               
    11.             DragManager.doDrag(dragInitiator, ds, event);           
    12.     }
    13.  
    14.         private function dragEnterHandler(event:DragEvent):void {
    15.                 if (event.dragSource.hasFormat("desk"))
    16.                 {
    17.                    DragManager.acceptDragDrop(Canvas(event.currentTarget));
    18.                
    19.                 }
    20.         }

    Si quelqu'un peut m'aider, je le remercie d'avance.

  2. Salut,
    dans ton implémentation, tu prend le localX / localY de l'évènement MouseEvent. Celui-ci est donc relatif au premier conteneur. Essaie avec les propriétés stageX et stageY si tu veux récupérer les coordonnées par rapport au stage. Si cela ne fait toujours pas ce que tu souhaites, essaie de te débrouiller avec les méthodes globalToLocal() et localToGlobal() de la classe DisplayObject pour convertir tes coordonnées souris:
    http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/display/DisplayObject.html

    Bonne chance!
    Fabien

  3. Bonjour,

    Est-ce qu'il est possible de récupérer un drag issu de Windows.

    Par exemple un fichier (plus exactement son nom et son emplacement).

    Merci d'avance.

  4. Salut Eric,
    Cela n'est pas possible pour une application Web, seule une application native (AIR) peut accéder à ces informations notamment grâce au NativeDragManager:
    http://livedocs.adobe.com/flex/3/langref/flash/desktop/NativeDragManager.html

    Fabien


Leave a comment

(required)

Aucun trackbacks pour l'instant