Back-End

25 fev, 2008

Animação dinâmica com Prototype: Função fadeMotion

Publicidade

Olá amigos. Novamente estou por aqui em mais um artigo de Actionscript. E agora eu não paro mais!

Vou compartilhar com vocês uma função muito útil no meu dia-a-dia do desenvolvimento de animações dinâmicas: a função fadeMotion. Ela, na verdade, é uma melhoria (e bota melhoria nisso), de um cálculo que peguei na internet à um tempo atrás, para fazer o posicionamento de movieclips com um efeito “deslizante”. Para facilitar ainda mais o manuseio, eu criei um prototype (que utilizarei em alguns artigos) para a classe MovieClip.

Quando aplicada a função fadeMotion, o clipe irá “deslizar” para os valores _x,_y,_width,_height,_alpha informados, de acordo com a velocidade definida.

Detalhes deste artigo:

  • Versão de AS: ActionScrip 2.0
  • Compatibilidade: Flash Player 6 ++
  • Dificuldade de produção: 6
  • Dificuldade de aplicação: 6
  • Produzido em: Versão inicial – 2hs

Crie um arquivo de ActionScript (extensão .as), e nomeie-o como “MovieClipProts”. Neste arquivo, eu costumo colocar todos os prototypes úteis para MovieClip.

Para incluir este arquivo no seu Flash, você pode colocar o .as na mesma pasta e utilizar o seguinte comando:

#include "MovieClipProts.as" 

Cole o código abaixo no arquivo que acabou de criar:

//variáveis//##########################################//
// FADE MOTION COM PROTOTYPE
// VERSÃO: 1.7 - 05/12/2007
// DESENVOLVIDO POR: Weverton Naves (tom.naves@gmail.com) 
//##########################################//
MovieClip.prototype.fadeMotion = function(X, Y, W, H, A, vXY, vWH, vA) {
//cria o movieClp de controle
var fadeMontionControl = this.createEmptyMovieClip("fadeMontionControl", this.getNextHighestDepth());
this.fadeComplete = false;
//controle
if (vXY == undefined) {
vXY = 3;
}
if (vWH == undefined) {
vWH = 3;
}
if (vA == undefined) {
vA = 2;
//o dois funciona melhor
}
fadeMontionControl.onEnterFrame = function() {
//variáveis
var min:Number = 0.2;
//posição x
if (X == undefined || X == true) {
X = true;
} else {
if (X != this._parent._x) {
//se Xorigem for maior que Xdestino
if (X<this._parent._x) {
//diferença
dif = (this._parent._x-X)/vXY;
//passa pra positivo
if (dif<0) {
dif = dif*(-1);
}
//se Xdestino for maior que Xorigem 
} else {
//diferença
dif = (X-this._parent._x)/vXY;
//passa pra positivo
if (dif<0) {
dif = dif*(-1);
}
}
valida = dif>min;
if (valida) {
this._parent._x += (X-this._parent._x)/vXY;
} else {
this._parent._x = X;
}
} else {
X = true;
}
}
//posição y
//passa para negativo
if (Y == undefined || Y == true) {
Y = true;
} else {
if (Y != this._parent._y) {
if (Y<this._parent._y) {
//diferença
dif = (Y-this._parent._y)/vXY;
//passa pra positivo
if (dif<0) {
dif = dif*(-1);
}
} else {
//diferença
dif = (this._parent._y-Y)/vXY;
//passa pra positivo
if (dif<0) {
dif = dif*(-1);
}
}
valida = dif>min;
if (valida) {
this._parent._y += (Y-this._parent._y)/vXY;
} else {
this._parent._y = Y;
}
} else {
Y = true;
}
}
//largura -não pode ser negativo
if (W == undefined || W == true) {
W = true;
} else {
if (W != this._parent._width) {
if (W>this._parent._width) {
//diferença
dif = (W-this._parent._width)/vWH;
//passa pra positivo
if (dif<0) {
dif = dif*(-1);
}
} else {
//diferença
dif = (this._parent._width-W)/vWH;
//passa pra positivo
if (dif<0) {
dif = dif*(-1);
}
}
valida = dif>min;
if (valida) {
this._parent._width += (W-this._parent._width)/vWH;
} else {
this._parent._width = W;
}
} else {
W = true;
}
}
//altura - não pode ser negativo
//se não estiver definido
if (H == undefined || H == true) {
H = true;
} else {
if (H != this._parent._height) {
if (H>this._parent._height) {
//diferença
dif = (H-this._parent._height)/vWH;
//passa pra positivo
if (dif<0) {
dif = dif*(-1);
}
} else {
//diferença
dif = (this._parent._height-H)/vWH;
//passa pra positivo
if (dif<0) {
dif = dif*(-1);
}
}
valida = dif>min;
if (valida) {
this._parent._height += (H-this._parent._height)/vWH;
} else {
this._parent._height = H;
}
} else {
H = true;
}
}
//alpha
if (A == undefined || A == true) {
A = true;
} else {
if (A != this._parent._alpha) {
//se for diminuir
if (this._parent._alpha>A) {
if (((this._parent._alpha-A)/vA)<min) {
A = true;
} else {
resultado = (this._parent._alpha-A)/vA;
//se começar a repetir
this._parent._alpha -= resultado;
}
//se for aumentar
} else {
if (((A-this._parent._alpha)/vA)<min) {
A = true;
} else {
resultado = (A-this._parent._alpha)/vA;
//se começar a repetir
this._parent._alpha += resultado;
}
}
} else {
A = true;
}
}
//trace(this._parent._name+":: X: "+this._parent._x+" = "+X+" Y: "+this._parent._y+" = "+Y+" Width: "+this._parent._width+" = "+W+" height: "+this._parent._height+" = "+H+" alpha: "+this._parent._alpha+" = "+A);
//if ((this._parent._height == H) && (this._parent._x == X) && (this._parent._y == Y) && (this._parent._width == W) && (this._parent._alpha == A)) {
if (X == true && Y == true && W == true && H == true && A == true) {
this._parent.fadeComplete = true;
this._parent.onFadeComplete();
delete this.onEnterFrame;
}
};
};

Como funciona este prototype?

Um prototype é, na verdade, um método da classe MovieClip, muito poderoso, onde você pode adicionar outros métodos a essa mesma classe. Sabe aquelas funções que a gente usa muito e sempre tem que ficar criando ou copiando? Essa é a solução.

No caso, atribui a função fadeMotion() na classe MovieClip através do método prototype.

Utilizando a função fadeMotion()

Para utilizar essa função, é só adicioná-la na frente da referência ao seu MovieClip. Tenhamos como exemplo um movieClip chamado “myMC”:

myMC.fadeMotion(0,0,200,200,50,2,2,2)

Parâmetros da função fadeMotion()

A função tem os seguintes parâmetros:

fadeMotion(X,Y,W,H,A,vXY,vWA,vA)

Valores de destino no MovieClip

X = valor _x (posição horizontal)

Y = valor _y (posição vertical)

W = valor de _width (largura)

H = valor de _height (altura)

A = valor de _alpha (transparência)

vXY = velocidade da animação de posição

vWH = velocidade da animação de transformação

vA = velocidade da animação de transparência.

Não é necessário informar todos os parâmetros, mas lembre-se de que os parâmetros anteriores aos informados devem ser informados como “undefined”. Ex:

fadeMotion(undefined,undefined,50)

fadeMotion(undefined,100,undefined,10,undefined)

As velocidades já vem com o valor padrão de “3” para vWH e vXY, e valor “2” para vY.

Caso queira alterar, valores (que podem ser fracionários) abaixo dos acima aumentam a velocidade, e vice-versa.

Como funciona a função

Como eu havia dito, a função é baseada no seguinte cálculo (exemplo para posição _x):

(X-_x)/velocidade;

Este cálculo pega o valor de destino da posição, subtrai pelo valor atual da posição. Essa diferença é dividida pela velocidade e adiconada á posição atual, conforme código abaixo:

_x += (X-_x)/velocidade;

Como o resultado do cálculo é cada vez menor, a posição vai adiconando valores cada vez menores, gerando o efeito de “deslize”

Um bug da versão inicial, agora corrigido

Nas primeiras versões dessa função, percebi que quado eu a utilizava em um MovieClip, não podia utillizar outros comandos baseados em onEnterFrame (pois o cálculo é repetido através deste evento). Daí então, fiz a atualização que corrige esse bug: Criei um MovieClip dentro do MovieClip pai, como nome de fadeControl, que faz os cálculos, e evita que o evento onEnterFrame seja atribuido ao MovieClip pai.

O evento onFadeComplete

A cada onEnterFrame do fadeControl, ele faz uma verificação se todas as animações (posição, forma e transparência) foram concluídas. Caso positivo, ele seta um evento à função (onFadeComplete) e define a variável fadeComplete como “true”.

Neste caso, podemos chamar a função para animar nosso MovieClip, e ainda temos a possibilidade de executarmos uma ação quando a animação terminar,desta maneira:

meuMC.fadeMotion(20,50,undefined,20)
meuMC.onFadeComplete = function(){
trace("acabou a animação") 
} 

Também podemos saber se a animação está completa em determinado momento, fazendo a verificação se a variável fadeComplete está como true:

if(meuMC.fadeComplete){
trace("acabou a animação") 
}

Exemplo

NOTAS FINAIS

– O código aparenta ser bem complicadinho, mas com um tempo dedicado á entendê-lo, vai poupar muito tempo nas animações.

– Você pode fazer o download dos arquivos clicando aqui.

– Visite o meu blog, ou acesse o fórum iMasters para postar alguma dúvida.

Abraços!