2012-10-01 5 views
4

무대 좌표 (x, y)가 주어지면 사용자가 위치 (x, y)에서 클릭 한 것처럼 플래시 응용 프로그램을 동작하게하고 싶습니다. 즉, 이와 비슷한 것입니다.Actionscript 3에서 마우스 이벤트 시뮬레이션

function simulateClick(x:Number, y:Number):void{ 
    var e:MouseEvent = new MouseEvent(MouseEvent.CLICK, true, false, x, y) 
    stage.dispatchEvent(e); 
} 

나는 이러한 종류의 문제에 대해 이야기하는 많은 페이지를 발견했으며, 모두 위와 비슷한 솔루션을 제공합니다. 그러나 이것은 (x, y)에서 사용자가 클릭하는 것과 동일하지 않습니다. 두 가지 문제가 있습니다 :

첫 번째는 e.stageX와 e.stageY가 둘 다 0이라는 것입니다. 직접 설정할 수는 없습니다. e.localX와 e.localY가 설정되었을 때 문서가 계산되지만, dispatchEvent 전에 e.localX를 설정하거나 이벤트 리스너에서는 설정하지 않았다고 설명합니다.

var p:Point = e.target.localToGlobal(new Point(e.localX, e.localY)); 

이 유일한 옵션이다 :이 같은 내 이벤트 리스너를 모두 다시 수

?

두 번째 문제는 내 이벤트 리스너가 스테이지 자체가 아닌 스테이지의 자식들과 함께 등록된다는 것입니다. 그래서 dispatchEvent를 호출 할 대상을 찾아야합니다. 분명히 Flash는 대상이 무엇인지, 즉 어떤 객체가 위치 (x, y)에서 보이는 최상위 픽셀을 소유하는지 결정할 수 있습니다. 왜냐하면 사용자가 실제로 클릭 할 때 그렇게하기 때문입니다. 이 정보를 얻을 수있는 쉬운 방법이 있습니까? 아니면 동일한 작업을 수행하기 위해 자체 재귀 함수를 작성해야합니까? 나는 현재 DisplayObjectContainer.getObjectsUnderPoint를 사용하고 있습니다. 그러나 꽤 옳지 않습니다.

차이점이 있으면 FlashDevelop에서 작성 중입니다.

+0

getObjectsUnderPoint()는 첫 번째 InteractiveObject를 반환하지만 모양 만 반환합니다. 이것은 설명서의 누락이거나 버그입니다. –

답변

0

질문 1 : MouseEvent (로컬 x, y 할당)를 만든 후에는 e.stageX를 직접 참조하고 이벤트를 보내기 전에 원하는대로 설정할 수 있어야합니다. MouseEvent 인스턴스의 속성 일뿐입니다. # 2의 경우 currentTarget은 항상 마우스 아래에있는 것이고 target은 이벤트를 전달하는 것입니다. 이벤트가 진정으로 마우스 상호 작용에 의해 전달되었다고 가정합니다. 귀하의 경우에는 이벤트를 전달한 객체가되도록 대상을 설정할 수 있으며 currentTarget을 임의로 설정할 수 있습니다. 문제는 현재 이것이 바로 마우스 밑에있는 것을 다루는 가장 효율적인 방법인지 여부입니다. 그 대답은 아마 그렇지 않을 것이다. MOUSE_OVER 이벤트를 사용하여 마우스가 지금 무엇인지 탭하고, 이것을 호출 할 때 사용할 수있는 변수로 저장하고 전체 디스플레이 체인을 반복하지 않는 것이 좋습니다. 항상 (플래시가 네이티브로 루프에서 수행 할 수있는 속도보다 훨씬 빠르기 때문에). 스테이지에 mouseOver를 놓고 현재 대상을 확인하면 변경되는 모든 프레임에서 마우스 아래에있는 최상위 항목이 무엇이든 가져올 수 있습니다.

(명백한 불쾌한 스크립트를 방지하기 위해) 특정 동작은 actionscript에 의해 동적으로 생성 된 마우스 이벤트에 의해 트리거 될 수 없음을 알아야합니다. 여기에는 파일 참조 열기 및 전체 화면 이동이 포함됩니다.

1

e.stageX/Y은 나를 위해 올바르게 채워집니다 ... getObjectsUnderPoint()은 정상적으로 작동하는 것 같습니다. 나는 x/y 값이 simulateClick에 전달되었다고 가정하고 있습니다. 전역 좌표입니까?

편집 : 의견에서 지적한대로 마우스 이벤트는 InteractiveObject 인스턴스에서 전달되어야합니다. 그에 따라 코드가 수정되어야합니다.

import flash.display.Bitmap; 
import flash.display.BitmapData; 
import flash.display.DisplayObject; 
import flash.display.InteractiveObject; 
import flash.display.Sprite; 
import flash.events.MouseEvent; 
import flash.geom.Point; 

public function simulateClick(x:Number, y:Number):void 
{ 
    var objects:Array = stage.getObjectsUnderPoint(new Point(x, y)); 

    var target:DisplayObject; 
    while(target = objects.pop()) 
    { 
     if(target is InteractiveObject) 
     { 
      break; 
     } 
    } 

    if(target !== null) 
    { 
     var local:Point = target.globalToLocal(new Point(x, y)); 

     var e:MouseEvent = new MouseEvent(MouseEvent.CLICK, true, false, local.x, local.y); 
     target.dispatchEvent(e); 
    } 
} 

public function addedToStage():void 
{ 
    var parent:Sprite = new Sprite(); 
    stage.addChild(parent); 

    var child:Sprite = new Sprite(); 
    child.name = 'child 1'; 
    child.graphics.beginFill(0xff0000, 1); 
    child.graphics.drawRect(0, 0, 200, 200); 
    child.graphics.endFill(); 

    var child2:Sprite = new Sprite(); 
    child2.name = 'child 2'; 
    child2.graphics.beginFill(0xff00ff, 1); 
    child2.graphics.drawRect(0, 0, 100, 100); 
    child2.graphics.endFill(); 
    child2.x = 150; 
    child2.y = 150; 

    var bmpData:BitmapData = new BitmapData(80, 80, false, 0x00ff00); 
    var bmp:Bitmap = new Bitmap(bmpData); 
    bmp.name = 'bitmap'; 

    child2.addChild(bmp); 

    parent.addChild(child); 
    parent.addChild(child2); 

    child2.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void 
    { 
     trace('target: ' + e.target.name); 
     trace('localX: ' + e.localX); 
     trace('localY: ' + e.localY); 
     trace('stageX: ' + e.stageX); 
     trace('stageY: ' + e.stageY); 
    }); 

    simulateClick(190, 190); 
} 

출력 : 나도이 문제를 직면

target: child 2 
localX: 40 
localY: 40 
stageX: 190 
stageY: 190 
+1

응답 해 주셔서 감사합니다. 더 조사한 후 e.stageX에 대한 내 문제는 대상이 Sprite가 아닌 Bitmap 인 경우에만 발생합니다 (Bitmap이 InteractiveObject의 하위 클래스가 아니기 때문일 수 있습니다). 귀하의 예제를 따라하려고하지만 대상이 하나가 아닌 경우 InteractiveObject를 검색하여 등반 해 보겠습니다. – stewbasic

+0

그래, 그게 문제인 것 같아요, 비 - InteractiveObjects는 클릭 할 수 없습니다. 목록을 보면서 InteractiveObject 인스턴스를 검색하면 트릭을 수행하는 것 같습니다. 코드 예제를 업데이트했습니다. – ndm

0

는 나에게 두통의 비트를했다. 제 상황에서는 이벤트를 작성하면서 복잡한 계산을 약간 수행했지만 이미 로컬 좌표를 설정 했더라도 전역 좌표를 검색 할 수 없었습니다.

사실이 솔루션은 다른 방법 이벤트가 글로벌 로컬 변환하는 방법을 알고 있습니다, 글로벌 좌표가 이벤트가를 파견 한 후에 만 ​​채워집니다 ... 내 경우에는 매우 명백했다?

이것은 또 다른 함정이며, 위에는 InteractiveObject 인 이벤트를 발송하는 데 사용 된 개체를 확인하지 않습니다.

두 가지 함정으로 인해 다른 사람이이 문제에 직면 할 수 있기 때문에 게시합니다. 읽기 쉬운 빠른 답변.

관련 문제