[as3][翻译]改变display对象位置,创建拖动效果
不管你使用哪种display对象,所有的display对象共有一些操作。比如,它们都可以放置在屏幕上,在深度堆栈中前移或后移,被缩放、旋转等等。因为所有display对象都是从相同的基类(DisplayObject)中继承的这些功能,因此不管你操纵TextField实例、Video实例、Shape实例,还是其他的一些display对象,这些功能的表现是一样。
一、改变位置
对于任何一个display对象经常做的操作就是把它放置到屏幕上。要设置一个display对象的位置,改变它的x和y属性。
- myShape.x = 17;
- 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()方法,把全局舞台坐标转换成局部坐标,像下面这样:
- // Position the shape at the top-left corner of the Stage,
- // regardless of where its parent is located.
- // Create a Sprite, positioned at x:200 and y:200.
- var mySprite:Sprite = new Sprite();
- mySprite.x = 200;
- mySprite.y = 200;
- this.addChild(mySprite);
- // Draw a dot at the Sprite's 0,0 coordinate, for reference.
- mySprite.graphics.lineStyle(1, 0x000000);
- mySprite.graphics.beginFill(0x000000);
- mySprite.graphics.moveTo(0, 0);
- mySprite.graphics.lineTo(1, 0);
- mySprite.graphics.lineTo(1, 1);
- mySprite.graphics.lineTo(0, 1);
- mySprite.graphics.endFill();
- // Create the circle Shape instance.
- var circle:Shape = new Shape();
- mySprite.addChild(circle);
- // Draw a circle with radius 50 and center point at x:50, y:50 in the Shape.
- circle.graphics.lineStyle(1, 0x000000);
- circle.graphics.beginFill(0xff0000);
- circle.graphics.drawCircle(50, 50, 50);
- circle.graphics.endFill();
- // Move the Shape so its top-left corner is at the Stage's 0, 0 coordinate.
- var stagePoint:Point = new Point(0, 0);
- var targetPoint:Point = mySprite.globalToLocal(stagePoint);
- circle.x = targetPoint.x;
- circle.y = targetPoint.y;
同样的,也可以使用DisplayObject对象的localToGlobal()方法把局部坐标转换成全局坐标。
2、创建一个拖动交互
要移动对象的一个常见原因是要创建拖动效果,也就是当用户点击了某个对象,这个对象跟随鼠标移动,直到鼠标按钮被释放。有两种使用ActionScript创建拖动效果的方法。不管哪种方法,都要使用两个鼠标事件:当鼠标按下的时候,对象要开始跟随鼠标,当释放鼠标的时候,对象停止跟随鼠标。
第一种方法,使用startDrag()方法,很简单,但是限制也多。当按下鼠标的时候,被拖动的display对象的startDrag()方法被调用。当释放鼠标的时候,调用stopDrag()方法。
- // This code creates a drag-and-drop interaction using the startDrag()
- // technique.
- // square is a DisplayObject (e.g. 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()拖动一个对象,而又对另一个对象调用了startDrag()方法,那么第一个对象将马上停止跟随鼠标。比如像下面这样,尽管square.startDrag()也调用了,但是只有圆形会被拖动:
- function startDragging(event:MouseEvent):void
- {
- square.startDrag();
- circle.startDrag();
- }
一个事实是使用startDrag()在同一时间只能有一个对象被拖动,任何对象都可以调用stopDrag()方法,它会马上停止拖动,而不管当前是否正在被拖动。
如果你想拖动多个对象,或者要避免可能有多个对象使用startDrag()而引发的困难,最好的方法是使用鼠标跟随技术实现拖动效果。使用这种技术,当鼠标按下的时候,一个函数被添加为Stage的mouseMove事件的监听器。只要鼠标一移动这个函数就会执行,它将被拖动对象移到鼠标的x、y坐标处。当鼠标释放的时候,就取消了这个函数监听作用,也就是说当鼠标再移动的时候它也不会被调用,该对象也停止跟随鼠标光标。下面的代码展示了这种技术:
- // This code creates a drag-and-drop interaction 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);
在实现拖动效果中,除了要让display对象跟随鼠标光标,还要把被拖动对象移到前面显示,这样它才能在所有对象的上方移动。比如,假如有两个对象:一个圆形和一个正方形,而在display链中,圆形位于正方形之下,因此当拖动圆形经过正方形的时候,光标会在正方形上方,但是圆形却在正方形下方,影响了拖动效果。因此,当圆形被点击的时候,你要把它移到display链的顶端,这样它就会显示在所有内容的上方了。
下面这段代码(根据前面的代码改变)对两个对象,一个圆、一个正方形,创建了拖动效果。无论在哪个对象上按下了鼠标,那个对象就会移到Stage显示链的顶端,这样被拖动的元素总是在顶部显示。
- // 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);
继续扩展这个效果,比如游戏中在堆之间移动游戏中的货币或者卡片,当它被捡起的时候,你需要把添加到Stage的显示链中,而当鼠标在某一“堆”上释放时,又需要把拖动的对象添加到其他显示链中。
最后,为了增强这个效果,你可以对在拖动的时候给对象加一个阴影滤镜,然后在停止拖动的时候删除滤镜效果。

Leave a Reply