ActionScript Strange Coords após o RemoveChild é chamado
-
22-09-2019 - |
Pergunta
Alguém pode me ajudar a entender o seguinte?
Crie alguns sprites quadrados e depois removo o primeiro e exibo os coordenados. O resultado é:
(x=0, y=0, w=208, h=40) 0 208
(x=42, y=0, w=166, h=40) 0 166
A coordenada X ainda é 0, embora a largura tenha mudado, o getBounds mostra valores corretos. Eu esperaria que X mudasse também. Devido ao valor errado de X, o trabalho global -tolocal e localtoglobal incorretamente.
Se você clicar em algum lugar do lado esquerdo do segundo retângulo (ainda visível), você recebe:
2 28 (x=2, y=28)
O que é bom para nada. Os valores entre colchetes devem estar em coordenados de palco e não são.
O código:
public function test():void {
var s:Sprite;
var i:int;
var arr:Array = new Array();
for (i = 0; i < 5; ++i)
{
s = new Sprite();
s.graphics.beginFill(0x999);
s.graphics.drawRect(0, 0, 40, 40);
s.graphics.endFill();
s.x = i * 42;
arr.push(s);
addChild(s);
}
trace(this.getBounds(stage), x, width);
removeChild(arr[0]); arr[0] = null;
trace(this.getBounds(stage), x, width);
addEventListener(MouseEvent.CLICK, click);
}
private function click(e:MouseEvent):void {
trace(e.localX, e.localY, localToGlobal(new Point(e.localX, e.localY)));
}
Solução
Você está confuso em dois pontos separados, mas acho que cada um decorre de uma visão incompleta de como o Flash lida com os sistemas de coordenadas. Lembre -se de que todo objeto de exibição carrega em torno de seu próprio sistema de coordenamento. Em sua primeira pergunta, as propriedades "X" e "Y" de um objeto não são calculadas dinamicamente para refletir o canto superior esquerdo do objeto, eles simplesmente denotam a localização da origem desse objeto, com relação ao sistema de coordenadas de seus pais. Portanto, o valor "X" de um objeto não mudará apenas porque o conteúdo do objeto mudou - ele muda quando você move o próprio objeto.
O problema com suas coordenadas de estágio é que o localToGlobal
O método converte coordenadas do escopo em que se chama - e você está chamando de pai dos retângulos, mas você está passando em coordenadas do sistema local dentro do retângulo. Olhe para seguir um pouco e deve fazer sentido:
function click(e:MouseEvent):void {
// bad - uses rectangle coords in scope of "this"
//trace(e.localX, e.localY, localToGlobal(new Point(e.localX, e.localY)));
// works - call localToGlobal from the scope of the rectangle
trace( e.target.localToGlobal(new Point(e.localX, e.localY)));
// alternately, call it from any scope with coordinates taken from that scope:
trace( localToGlobal( new Point( mouseX, mouseY )));
trace( e.target.localToGlobal( new Point( e.target.mouseX, e.target.mouseY )));
}
Atualizar:Parte do que torna isso confuso é como o evento Bubbling funciona no AS3. Leia os primeiros parágrafos de Este excelente artigo Para obter a ideia geral e, em seguida, entenda que, neste exemplo, os eventos são emitidos inicialmente a partir de um retângulo (porque é onde é o gráfico que foi clicado), mas você apenas os pega enquanto eles borbulham o escopo em que você define seu ouvinte. Então e.target
é o retângulo e e.currentTarget
é o escopo do seu ouvinte. Então a peça final do quebra -cabeça é entender que e.localX
e e.localY
estão sempre no sistema de coordenadas do alvo original do evento. (Isso ocorre porque são propriedades do evento, e não faria sentido para que eles continuassem mudando à medida que o evento borbulhava a lista de exibição.)
Como nota final, se você está se perguntando como os iniciantes geralmente lidam com essas coisas, a resposta é que as pessoas geralmente anexam ouvintes diretamente ao objeto de exibição que possui o conteúdo gráfico que será clicado. Nesse caso, E.Target e E.CurrentTarget serão sempre os mesmos, e a maioria dos iniciantes não precisará entender nada disso.