我认为这是一项简单的任务,但我错了。
我使用精灵来显示图像,当用户拖动它时(MOUSE_DOWN和MOUSE_MOVE),我得到了MOUSE_MOVE
中的位置并计算了偏移量:
var current: Point = new Point(event.localX, event.localY);
sprite.x = current.x - start.x;
sprite.y = current.y - start.y;
它有效但不顺畅。有更好的解决方案吗?
更新
经过一天的调试,我终于找到了原因。
更大的 fps 可以让它更顺畅,但这不是这个问题的关键。
关键是我应该使用stage
来监听MOUSE_MOVE
,而不是图像本身。在获得鼠标位置时,我应该使用event.stageX/Y
(或stage.mouseX/Y
),而不是event.localX/Y
。来自运动图像的event.localX/Y
既不稳定也不平滑,导致我的问题。
以下是我的工作代码,享受它:)
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);
}
}
}
答案 0 :(得分:1)
您必须使用高帧率才能平稳移动。最佳帧率为60fps,因为它是大多数LCD显示器的默认值。
我手边没有代码所以我把代码放在这里(未经测试)
yourClip.addeventListenner(MouseEvent.MOUSE_DOWN, startDrag);
function startDrag(e:MouseEvent = null):void{
// record positon of the mouse relative to the clip
deltaX=stage.mouseX-yourClip.x;
deltaY=stage.mouseY-yourClip.y;
// attach on mouse move event
yourClip.addeventListenner(MouseEvent.MOUSE_MOVE, updateDrag);
// attach stop event (on Stage)
Stage.addeventListenner(MouseEvent.MOUSE_UP, stopDrag);
}
function updateDrag(e:MouseEvent = null):void{
yourClip.x=stage.mouseX-deltaX
yourClip.y=stage.mouseY-deltaY
}
function stopDrag(e:MouseEvent = null):void{
yourClip.removeEventListenner(MouseEvent.MOUSE_MOVE, updateDrag);
stage.removeEventListenner(MouseEvent.MOUSE_UP, stopDrag);
}
答案 1 :(得分:1)
如果你正在寻找平滑的拖动体验,这里有一个你可以使用的方法:(假设你正在拖动的东西叫'dragee',这个代码在dragee的父母的范围内)
function startDragging():void {
dragee.addEventListener(Event.ENTER_FRAME,dragUpdate);
}
function stopDragging():void {
dragee.removeEventListener(Event.ENTER_FRAME,dragUpdate);
}
var decay:Number = .25; //1 is no decay, .1 would be cazy slow
function dragUpdate(e:Event):void {
dragee.x += decay * (mouseX - dragee.x);
dragee.y += decay * (mouseY - dragee.y);
}
答案 2 :(得分:1)
在这里,试试这个。它只是一个简单的黑色方块,但它看起来很好,直到你真的开始拖动它。如前所述,将帧率设置为更高的值是理想的。在这种情况下,我决定在MOUSE_DOWN中将帧速率提高到60fps,并在出于内存原因将其放回MOUSE_UP中的24。你显然可以改变你喜欢的方式。
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;
}
确保在MOUSE_UP上删除MOUSE_MOVE事件。这是关键。否则,您在每个MOUSE_DOWN上重新添加事件,并同时重复运行相同的代码。对不起,我的语法不是100%正确;我在CS5.5中非常快速地将它放在一起,而不是在Flash Builder中进行。
答案 3 :(得分:0)
尝试在拖动处理程序中调用event.updateAfterEvent()
。该函数告诉Flash立即重绘舞台,而不是等到下一帧。