I Love China

技术·人生

技术服务生活
繁體
6月 3rd, 2007

[as3][翻译]改变display对象位置,创建拖动效果

不管你使用哪种display对象,所有的display对象共有一些操作。比如,它们都可以放置在屏幕上,在深度堆栈中前移或后移,被缩放、旋转等等。因为所有display对象都是从相同的基类(DisplayObject)中继承的这些功能,因此不管你操纵TextField实例、Video实例、Shape实例,还是其他的一些display对象,这些功能的表现是一样。
一、改变位置
对于任何一个display对象经常做的操作就是把它放置到屏幕上。要设置一个display对象的位置,改变它的x和y属性。

ActionScript Code:
  1. myShape.x = 17;
  2. myShape.y = 212;

display对象放置系统把Stage看作一个笛卡尔坐标系统(有水平的x轴和垂直的y轴)。坐标系统的原点(x轴和y轴的交点,(0,0)点)在舞台的左上角。从这一点向右x值增加,向左x值减少,向上y值减少,向下y值增加。比如前面的代码把myShape移动到x坐标17(在原点右侧17像素)、y坐标212(在原点下方212像素)。
使用ActionScript创建的对象的默认x、y属性值都是0,也就是放在它的父级对象的左上角。
1、改变相对舞台的坐标
需要记住的重要一点就是display对象的x、y属性值都是相对于它的父级display对象坐标轴0,0点的位置。比如,一个Sprite实例中包含一个Shape实例(比如一个圆形),把这个Shape对象的x和y属性值设成0会把它放置到Sprite的左上角,但并不一定是舞台的左上角。要想把一个对象放置到相对全局舞台坐标中的某个位置处,可以对任何一个display对象使用globalToLocal()方法,把全局舞台坐标转换成局部坐标,像下面这样:

ActionScript Code:
  1. // Position the shape at the top-left corner of the Stage,
  2. // regardless of where its parent is located.
  3.  
  4. // Create a Sprite, positioned at x:200 and y:200.
  5. var mySprite:Sprite = new Sprite();
  6. mySprite.x = 200;
  7. mySprite.y = 200;
  8. this.addChild(mySprite);
  9.  
  10. // Draw a dot at the Sprite's 0,0 coordinate, for reference.
  11. mySprite.graphics.lineStyle(1, 0x000000);
  12. mySprite.graphics.beginFill(0x000000);
  13. mySprite.graphics.moveTo(0, 0);
  14. mySprite.graphics.lineTo(1, 0);
  15. mySprite.graphics.lineTo(1, 1);
  16. mySprite.graphics.lineTo(0, 1);
  17. mySprite.graphics.endFill();
  18.  
  19. // Create the circle Shape instance.
  20. var circle:Shape = new Shape();
  21. mySprite.addChild(circle);
  22.  
  23. // Draw a circle with radius 50 and center point at x:50, y:50 in the Shape.
  24. circle.graphics.lineStyle(1, 0x000000);
  25. circle.graphics.beginFill(0xff0000);
  26. circle.graphics.drawCircle(50, 50, 50);
  27. circle.graphics.endFill();
  28.  
  29. // Move the Shape so its top-left corner is at the Stage's 0, 0 coordinate.
  30. var stagePoint:Point = new Point(0, 0);
  31. var targetPoint:Point = mySprite.globalToLocal(stagePoint);
  32. circle.x = targetPoint.x;
  33. circle.y = targetPoint.y;

同样的,也可以使用DisplayObject对象的localToGlobal()方法把局部坐标转换成全局坐标。
2、创建一个拖动交互
要移动对象的一个常见原因是要创建拖动效果,也就是当用户点击了某个对象,这个对象跟随鼠标移动,直到鼠标按钮被释放。有两种使用ActionScript创建拖动效果的方法。不管哪种方法,都要使用两个鼠标事件:当鼠标按下的时候,对象要开始跟随鼠标,当释放鼠标的时候,对象停止跟随鼠标。
第一种方法,使用startDrag()方法,很简单,但是限制也多。当按下鼠标的时候,被拖动的display对象的startDrag()方法被调用。当释放鼠标的时候,调用stopDrag()方法。

ActionScript Code:
  1. // This code creates a drag-and-drop interaction using the startDrag()
  2. // technique.
  3. // square is a DisplayObject (e.g. a MovieClip or Sprite instance).
  4.  
  5. import flash.events.MouseEvent;
  6.  
  7. // This function is called when the mouse button is pressed.
  8. function startDragging(event:MouseEvent):void
  9. {
  10.     square.startDrag();
  11. }
  12.  
  13. // This function is called when the mouse button is released.
  14. function stopDragging(event:MouseEvent):void
  15. {
  16.     square.stopDrag();
  17. }
  18.  
  19. square.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
  20. square.addEventListener(MouseEvent.MOUSE_UP, stopDragging);

这种做法有一个限制:同一时间只能有一个对象使用startDrag()拖动。如果正在使用startDrag()拖动一个对象,而又对另一个对象调用了startDrag()方法,那么第一个对象将马上停止跟随鼠标。比如像下面这样,尽管square.startDrag()也调用了,但是只有圆形会被拖动:

ActionScript Code:
  1. function startDragging(event:MouseEvent):void
  2. {
  3.     square.startDrag();
  4.     circle.startDrag();
  5. }

一个事实是使用startDrag()在同一时间只能有一个对象被拖动,任何对象都可以调用stopDrag()方法,它会马上停止拖动,而不管当前是否正在被拖动。
如果你想拖动多个对象,或者要避免可能有多个对象使用startDrag()而引发的困难,最好的方法是使用鼠标跟随技术实现拖动效果。使用这种技术,当鼠标按下的时候,一个函数被添加为Stage的mouseMove事件的监听器。只要鼠标一移动这个函数就会执行,它将被拖动对象移到鼠标的x、y坐标处。当鼠标释放的时候,就取消了这个函数监听作用,也就是说当鼠标再移动的时候它也不会被调用,该对象也停止跟随鼠标光标。下面的代码展示了这种技术:

ActionScript Code:
  1. // This code creates a drag-and-drop interaction using the mouse-following
  2. // technique.
  3. // circle is a DisplayObject (e.g. a MovieClip or Sprite instance).
  4.  
  5. import flash.events.MouseEvent;
  6.  
  7. var offsetX:Number;
  8. var offsetY:Number;
  9.  
  10. // This function is called when the mouse button is pressed.
  11. function startDragging(event:MouseEvent):void
  12. {
  13.     // Record the difference (offset) between where
  14.     // the cursor was when the mouse button was pressed and the x, y
  15.     // coordinate of the circle when the mouse button was pressed.
  16.     offsetX = event.stageX - circle.x;
  17.     offsetY = event.stageY - circle.y;
  18.    
  19.     // tell Flash Player to start listening for the mouseMove event
  20.     stage.addEventListener(MouseEvent.MOUSE_MOVE, dragCircle);
  21. }
  22.  
  23. // This function is called when the mouse button is released.
  24. function stopDragging(event:MouseEvent):void
  25. {
  26.     // Tell Flash Player to stop listening for the mouseMove event.
  27.     stage.removeEventListener(MouseEvent.MOUSE_MOVE, dragCircle);
  28. }
  29.  
  30. // This function is called every time the mouse moves,
  31. // as long as the mouse button is pressed down.
  32. function dragCircle(event:MouseEvent):void
  33. {
  34.     // Move the circle to the location of the cursor, maintaining
  35.     // the offset between the cursor's location and the
  36.     // location of the dragged object.
  37.     circle.x = event.stageX - offsetX;
  38.     circle.y = event.stageY - offsetY;
  39.  
  40.     // Instruct Flash Player to refresh the screen after this event.
  41.     event.updateAfterEvent();
  42. }
  43.  
  44. circle.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
  45. circle.addEventListener(MouseEvent.MOUSE_UP, stopDragging);

在实现拖动效果中,除了要让display对象跟随鼠标光标,还要把被拖动对象移到前面显示,这样它才能在所有对象的上方移动。比如,假如有两个对象:一个圆形和一个正方形,而在display链中,圆形位于正方形之下,因此当拖动圆形经过正方形的时候,光标会在正方形上方,但是圆形却在正方形下方,影响了拖动效果。因此,当圆形被点击的时候,你要把它移到display链的顶端,这样它就会显示在所有内容的上方了。
下面这段代码(根据前面的代码改变)对两个对象,一个圆、一个正方形,创建了拖动效果。无论在哪个对象上按下了鼠标,那个对象就会移到Stage显示链的顶端,这样被拖动的元素总是在顶部显示。

ActionScript Code:
  1. // This code creates a drag-and-drop interaction using the mouse-following
  2. // technique.
  3. // circle and square are DisplayObjects (e.g. MovieClip or Sprite
  4. // instances).
  5.  
  6. import flash.display.DisplayObject;
  7. import flash.events.MouseEvent;
  8.  
  9. var offsetX:Number;
  10. var offsetY:Number;
  11. var draggedObject:DisplayObject;
  12.  
  13. // This function is called when the mouse button is pressed.
  14. function startDragging(event:MouseEvent):void
  15. {
  16.     // remember which object is being dragged
  17.     draggedObject = DisplayObject(event.target);
  18.    
  19.     // Record the difference (offset) between where the cursor was when
  20.     // the mouse button was pressed and the x, y coordinate of the
  21.     // dragged object when the mouse button was pressed.
  22.     offsetX = event.stageX - draggedObject.x;
  23.     offsetY = event.stageY - draggedObject.y;
  24.    
  25.     // move the selected object to the top of the display list
  26.     stage.addChild(draggedObject);
  27.    
  28.     // Tell Flash Player to start listening for the mouseMove event.
  29.     stage.addEventListener(MouseEvent.MOUSE_MOVE, dragObject);
  30. }
  31.  
  32. // This function is called when the mouse button is released.
  33. function stopDragging(event:MouseEvent):void
  34. {
  35.     // Tell Flash Player to stop listening for the mouseMove event.
  36.     stage.removeEventListener(MouseEvent.MOUSE_MOVE, dragObject);
  37. }
  38.  
  39. // This function is called every time the mouse moves,
  40. // as long as the mouse button is pressed down.
  41. function dragObject(event:MouseEvent):void
  42. {
  43.     // Move the dragged object to the location of the cursor, maintaining
  44.     // the offset between the cursor's location and the location
  45.     // of the dragged object.
  46.     draggedObject.x = event.stageX - offsetX;
  47.     draggedObject.y = event.stageY - offsetY;
  48.    
  49.     // Instruct Flash Player to refresh the screen after this event.
  50.     event.updateAfterEvent();
  51. }
  52.  
  53. circle.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
  54. circle.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
  55.  
  56. square.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
  57. square.addEventListener(MouseEvent.MOUSE_UP, stopDragging);

继续扩展这个效果,比如游戏中在堆之间移动游戏中的货币或者卡片,当它被捡起的时候,你需要把添加到Stage的显示链中,而当鼠标在某一“堆”上释放时,又需要把拖动的对象添加到其他显示链中。
最后,为了增强这个效果,你可以对在拖动的时候给对象加一个阴影滤镜,然后在停止拖动的时候删除滤镜效果。

随机文章:

Leave a Reply