如何拖动图像平滑地移动它在屏幕上,使用ActionScript?拖动、平滑、它在、图像

2023-09-08 12:20:00 作者:夜袭

我在想这是个简单的任务,但是我错了。

我用了一个精灵来显示图像,而当用户拖动它(MOUSE_DOWN和MOUSE_MOVE),我得到的位置 MOUSE_MOVE 和计算的偏移量:

 无功电流:点=新的点(event.localX,event.localY);
 sprite.x = current.x  -  start.x;
 sprite.y = current.y  -  start.y;
 

它的工作原理,但并不顺利。有没有更好的解决办法?

更新

调试了一天之后,我终于找到了原因。

更大的 FPS 可以让它流畅,但它不是对这个问题的关键所在。

关键是我应该使用来听 MOUSE_MOVE ,而不是图像本身。并获得鼠标位置的时候,我应该使用 event.stageX / Y (或 stage.mouseX / Y ),没有 event.localX / Y 。该 event.localX / Y 从运动图像,既不稳定,也不流畅,导致我的问题。

以下是我的工作code,乐在其中:)

 包{
    匹配import flash.display.Bitmap;
    进口flash.display.Loader;
    进口flash.display.Sprite;
    进口对象类型:flash.events.Event;
    进口flash.events.MouseEvent;
    进口flash.geom.Matrix;
    进口flash.geom.Point;
    进口flash.net.URLRequest;
    进口API元素flash.text.TextField;

    公共类DragIssue扩展Sprite {

        私有静态常量网址:字符串=财产/ m1.jpg;

        私人VAR自:DragIssue;

        私人VAR精灵:精灵;

        私人VAR的startPoint:点;

        私人VAR offsetX:数= 0;
        私人VAR offsetY:数= 0;

        公共职能DragIssue(){
            自=这一点;
            在里面();
            的LoadImage();
        }

        保护功能的init():无效{
            如果(阶段== NULL){
                this.addEventListener(Event.ADDED_TO_STAGE,on_addedToStage);
            } 其他 {
                stage.addEventListener(的MouseEvent.MOUSE_MOVE,的OnMouseMove);
            }

            功能on_addedToStage(事件:事件):无效{
                self.removeEventListener(Event.ADDED_TO_STAGE,on_addedToStage);
                stage.addEventListener(的MouseEvent.MOUSE_MOVE,的OnMouseMove);
            }
        }

        公共职能的LoadImage():无效{
            VAR装载机:装载机=新的Loader();
            loader.contentLoaderInfo.addEventListener(引发Event.COMPLETE,imageLoaded);
            loader.load(新的URLRequest(URL));

            功能imageLoaded(事件:事件):无效{
                VAR位:位图= event.target.content为位图;

                self.sprite =新的Sprite();
                sprite.addChild(位);

                self.addChild(精灵);

                sprite.addEventListener(的MouseEvent.MOUSE_DOWN,onmousedown事件);
                sprite.addEventListener(侦听MouseEvent.MOUSE_UP,onMouseUp);
            }
        }

        私有函数的OnMouseMove(事件:MouseEvent)方法:无效{
            如果(的startPoint){
                sprite.x = offsetX + event.stageX  -  startPoint.x;
                sprite.y = offsetY + event.stageY  -  startPoint.y;
            }
        }

        私有函数onMouseUp(事件:MouseEvent)方法:无效{
            的startPoint = NULL;
            offsetX = sprite.x;
            offsetY = sprite.y;
        }

        私有函数onmousedown事件(事件:MouseEvent)方法:无效{
            的startPoint =新的点(event.stageX,event.stageY);
        }

    }
}
 

解决方案 创建 ActionScript 移动设备项目

下面,试试这个。这只是一个简单的黑色正方形,但看起来很好,直到你的真正的开始拖拽它。正如所提到的,帧率设置为更高的东西是最理想的。在这种情况下,我决定了帧率在MOUSE_DOWN 60fps的落回至24日在MOUSE_UP内存的原因。可以很明显的改变,请您如何。

 进口flash.display使用*。
进口flash.events *。


VAR STARTX:数字;
VAR startY:数​​字;
VAR形状:雪碧=新的Sprite();
shape.graphics.beginFill(0x000000处);
shape.graphics.drawRect(0,0,50,50);
shape.graphics.endFill();
this.addChild(形状);

shape.addEventListener(的MouseEvent.MOUSE_DOWN,this.mouseDown);

功能MOUSEDOWN(E:的MouseEvent = NULL):无效{
    stage.frameRate = 60;
    STARTX = stage.mouseX  -  shape.x;
    startY = stage.mouseY  -  shape.y;
    stage.addEventListener(的MouseEvent.MOUSE_MOVE,this.mouseMove);
    shape.addEventListener(侦听MouseEvent.MOUSE_UP,this.mouseUp);
}

功能的mouseMove(E:的MouseEvent = NULL):无效{
    shape.x = stage.mouseX  -  STARTX;
    shape.y = stage.mouseY  -  startY;
}

功能mouseUp事件(E:的MouseEvent = NULL):无效{
    shape.removeEventListener(侦听MouseEvent.MOUSE_UP,this.mouseUp);
    stage.removeEventListener(的MouseEvent.MOUSE_MOVE,this.mouseMove);
    stage.frameRate = 24;
}
 

请确保您在MOUSE_UP去除MOUSE_MOVE事件。这是关键。否则,你再添加事件上的每个MOUSE_DOWN,最终重复运行相同的code,同时进行。很抱歉,我的语法是不是100%正确的;我在CS5.5扔了一起非常快的,而不是做在Flash Builder中。

I was thinking this is a simple task, but I'm wrong.

I used a sprite to display an image, and when user drag it(MOUSE_DOWN and MOUSE_MOVE), I got the position in MOUSE_MOVE and calculated the offsets:

 var current: Point = new Point(event.localX, event.localY);
 sprite.x = current.x - start.x;
 sprite.y = current.y - start.y;

It works but not smooth. Is there a better solution?

UPDATE

After a day of debugging, I finally found the reason.

Bigger fps can make it smoother, but it's not the key of this question.

The key is I should use stage to listen MOUSE_MOVE, not the image itself. And when getting the mouse position, I should use event.stageX/Y(or stage.mouseX/Y), not event.localX/Y. The event.localX/Y from the moving image, is neither stable nor smooth, that causes my problem.

Following is my working code, enjoy it :)

package {
    import flash.display.Bitmap;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.net.URLRequest;
    import flash.text.TextField;

    public class DragIssue extends Sprite {

        private static const URL: String = "assets/m1.jpg";

        private var self: DragIssue;

        private var sprite: Sprite;

        private var startPoint: Point;

        private var offsetX: Number = 0;
        private var offsetY: Number = 0;

        public function DragIssue() {
            self = this;
            init();
            loadImage();
        }

        protected function init(): void {
            if (stage == null) {
                this.addEventListener(Event.ADDED_TO_STAGE, on_addedToStage);
            } else {
                stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
            }

            function on_addedToStage(event: Event): void {
                self.removeEventListener(Event.ADDED_TO_STAGE, on_addedToStage);
                stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
            }
        }

        public function loadImage(): void {
            var loader: Loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded);
            loader.load(new URLRequest(URL));

            function imageLoaded(event: Event): void {
                var bitmap: Bitmap = event.target.content as Bitmap;

                self.sprite = new Sprite();
                sprite.addChild(bitmap);

                self.addChild(sprite);

                sprite.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
                sprite.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
            }
        }

        private function onMouseMove(event: MouseEvent): void {
            if (startPoint) {
                sprite.x = offsetX + event.stageX - startPoint.x;
                sprite.y = offsetY + event.stageY - startPoint.y;
            }
        }

        private function onMouseUp(event: MouseEvent): void {
            startPoint = null;
            offsetX = sprite.x;
            offsetY = sprite.y;
        }

        private function onMouseDown(event: MouseEvent): void {
            startPoint = new Point(event.stageX, event.stageY);
        }

    }
}

解决方案

Here, try this. It's just a simple black square, but it looks fine until you really start dragging it around. As was mentioned, setting the framerate to something higher is ideal. In this case, I decided to up the framerate to 60fps in the MOUSE_DOWN and drop it back to 24 in MOUSE_UP for memory reasons. You can obviously change that how you please.

import flash.display.*;
import flash.events.*;


var startX:Number;
var startY:Number;
var shape:Sprite = new Sprite();
shape.graphics.beginFill(0x000000);
shape.graphics.drawRect(0,0,50,50);
shape.graphics.endFill();
this.addChild(shape);

shape.addEventListener(MouseEvent.MOUSE_DOWN,this.mouseDown);

function mouseDown(e:MouseEvent = null):void{
    stage.frameRate = 60;
    startX = stage.mouseX - shape.x;
    startY = stage.mouseY - shape.y;
    stage.addEventListener(MouseEvent.MOUSE_MOVE,this.mouseMove);
    shape.addEventListener(MouseEvent.MOUSE_UP,this.mouseUp);
}

function mouseMove(e:MouseEvent = null):void{
    shape.x = stage.mouseX - startX;
    shape.y = stage.mouseY - startY;
}

function mouseUp(e:MouseEvent = null):void{
    shape.removeEventListener(MouseEvent.MOUSE_UP,this.mouseUp);
    stage.removeEventListener(MouseEvent.MOUSE_MOVE,this.mouseMove);
    stage.frameRate = 24;
}

Make sure you are removing the MOUSE_MOVE event on MOUSE_UP. That is key. Otherwise, you re-add the event on every MOUSE_DOWN and end up running the same code repeatedly, simultaneously. Sorry my syntax isn't 100% proper; I threw this together really quick in CS5.5 rather than doing it in Flash Builder.