Ir para conteúdo
Fórum Script Brasil
  • 0

Tutorial Conceito Arrastar


Pooh

Pergunta

Olá flasheiros

Venho aqui compartilhar algo que apesar de existirem vários por ai, foi preferível criar um do que procurar pronto...

Um efeito simples de arrastar e soltar, e ao fazer isso os objetos se mexerem de acordo com o quanto você arrastou.

Bom, peguei uma meia hora e bolei toda a execução e mais 30 minutos estou eu aqui compartilhando com vocês o fruto dessa necessidade.

Não está com as firulas mas está 100% funcional.

Vamos ao que interessa ;)

Arquivos:

Principal.Fla //aonde faremos nosso teste de aplicação

Dragable.as //é a nossa classe que diz como nosso objeto deve se comportar

DeltaDrag.as //é a classe que calcula e passa o parametro pro Dragable

Não se incomodem com o meu inglês, em alguns pontos da classe uso português em outros inglês...é a maldita influencia...você já pensa em inglês, escrever é consequência.

de qualquer forma é bem simples o raciocinio, uma classe da ao objeto as caracteristicas tipicas de velocidade e degradação da mesma e a outra classe se encarrega de guardar todos os objetos que serão afetados pelo drag/drop, calcula e passa via função do objeto.

O calculo que fiz pode ser facilmente substituído, pois fiz pensando no meu projeto.

Imaginei a diferença em distância de 2 pontos, ou seja o deltaDist. imaginei a diferença de tempo entre pressionar e soltar ou seja deltaTime;

lembram...distancia/tempo = velocidade ?

é exatamente o que vamos fazer... porém para arrumar o calculo adicionei uma constante que acerta a velocidade. esse acerto pode ficar mais bonito se feito no proprio objeto.

Vamos ao objeto:

package {

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

    public class Dragable extends Sprite {

        /* vars */
        
        private var SpeedX = 0;
        private var SpeedY = 0;        
        private var AcelX = 0;
        private var AcelY = 0;        
        private var SpeedDecay = 0.9;
        
        public function Dragable() {
            
            this.addEventListener(Event.ENTER_FRAME,refreshSelf);

        }
        
        /*Speed calcs*/

        public function AccX(val:Number){
            
            this.AcelX += val;
        
        }
        
        public function AccY(val:Number){
            
            this.AcelY += val;
        
        }        
        
        private function refreshSelf(e) {    
        
            SpeedX = AcelX;
            SpeedY = AcelY;
            
            AcelX *= SpeedDecay;
            AcelY *= SpeedDecay;            
            
            this.x += SpeedX;
            this.y += SpeedY;
            
            if( AcelX < 0.1 && AcelX > -0.1 ){
                
                AcelX = 0;
                
            }
            
            if( AcelY < 0.1 && AcelY >-0.1 ){
                
                AcelY = 0;
                
            }
        
        }
        
    }
}
Não há muito o que explicar, fiz o mais limpo possível... Extendi Sprite que é mais leve que MovieClip e possui suporte a eventos, temos ai variaveis separadas para os eixos X e Y. A minha degradação de velocidade ficou "melhor" em 0.9, quando menor, mais rapido o objeto para, quanto maior, mais ele demora, se for acima de 1 ao invés dele parar ele vai acelerar ou seja, não use... Adicionamos um listener para que ele fique fazendo um refresh no nosso objeto, para quem tiver vontade, pode adicionar um if no início, verificando se existe aceleração em X ou Y, assim evita ele ler todas as linhas e calcular nada, perda de performance em utilização mais complexa. Adicionei 2 setters para podermos adicionar uma aceleração ao nosso amigo, assim eu posso passar os resultados dos calculos realizados pela outra classe ao objeto. E a função de atualização, como todos conhecemos, a velocidade é algo simples de ser tratado. Transformamos aceleração diretamente em velocidade (pode adicionar uma aceleração gradativa, fiz uma passagem direta sem firulas...) Degradamos a aceleração atualizamos a posição de nosso objeto, afim de evitar que nosso objeto fique "tremendo" devido a degradação ser fruto de uma parte de sí mesmo ou seja, você sempre está pegando uma fração menor e não subtraindo, resumindo jamais se chega a zero. Para tratar isso delimitamos um intervalo ai de 0,1 para mais e para menos, assim, sempre que ele chegar nesse intervalo de aceleração ele zera e fica parado de vez... Agora ao gerenciador de drag/drop
package {

    import flash.events.*;
    import flash.geom.Point;
    import flash.display.Sprite;

    public class DeltaDrag extends Sprite {

        /*variaveis*/

        private var clickPoint:Point = new Point(0,0);
        private var releasePoint:Point = new Point(0,0);
        private var clickTime:Number = 0;
        private var releaseTime:Number = 0;
        private var SpeedConstant:Number = 21;
        private var affectedObjects:Array = new Array();
        
        private var lineObject:Sprite = new Sprite();
        private var objectHost;

        public function DeltaDrag(objectHost,objectsArray) {

            this.objectHost = objectHost;
            
            this.objectHost.addEventListener(MouseEvent.MOUSE_DOWN,pointClick);
            this.objectHost.addEventListener(MouseEvent.MOUSE_UP,pointRelease);

            this.objectHost.addChild(this.lineObject);
            
            this.affectedObjects = objectsArray;

        }
        
        private function refreshLine(e){
            
            this.lineObject.graphics.clear();
            this.lineObject.graphics.lineStyle(2,0xffffff);
            this.lineObject.graphics.moveTo(this.clickPoint.x,this.clickPoint.y);
            this.lineObject.graphics.lineTo(mouseX,mouseY);
            
        }
        
        private function pointClick(e) {

            this.clickPoint.x = mouseX;
            this.clickPoint.y = mouseY;

            var counter:Date = new Date();

            this.clickTime = counter.getTime();
            
            /*linha*/
            
            this.objectHost.addEventListener(Event.ENTER_FRAME,refreshLine);

        }
        
        private function pointRelease(e) {

            this.releasePoint.x = mouseX;
            this.releasePoint.y = mouseY;

            var counter:Date = new Date();

            this.releaseTime = counter.getTime();

            var deltaDistanceX:Number = this.releasePoint.x - this.clickPoint.x;
            var deltaDistanceY:Number = this.releasePoint.y - this.clickPoint.y;

            var deltaTime:Number = (this.releaseTime-this.clickTime) / 1000;

            var deltaX:Number = ( deltaDistanceX / ( deltaTime * this.SpeedConstant ) );
            var deltaY:Number = ( deltaDistanceY / ( deltaTime * this.SpeedConstant ) );

            refreshObjects(deltaX,deltaY);
            this.objectHost.removeEventListener(Event.ENTER_FRAME,refreshLine);
            this.lineObject.graphics.clear();

        }
        private function refreshObjects(valX:Number,valY:Number) {

            for each (var object in this.affectedObjects) {

                object.AccX(valX);
                object.AccY(valY);
            }
        }
    }
}
Novamente extendi sprite para pegar os eventos, chamei os Pontos mais por questão de gosto, pois são totalmente dispensáveis no armazenamento das posições de press e release... é preciso um objeto de referência pois é interessante usar essa funcionalidade em parte da nossa aplicação, no caso eu utilizei todo o stage, por isso opassei como parametro...assim como os objetos afetados, deixei como array, assim dando suporte a multiplos objetos afetados pelo drag...dai o nome affectedObjects :) Agora à nossa conta... a diferença entre as distâncias foi facilmente calculada através de 2 listeners... um para o evento de MOUSE_DOWN(press) e outro para o evento de MOUSE_UP(release) No evento de Press, gravamos as posições do nosso mouse em um ponto, e pegamos a hora atual na forma de milisegundos Adicionei ai uma pequena firula que foi o surgimento de uma linha guia que teoricamente demonstraria a "força" que você vai mover os objetos afetados, porém estou adicionando o enfraquecimento devido ao tempo, pois como diz a nossa conta, quanto menor o tempo e maior a distancia, mais rapido somos, quanto menor a distancia e maior o tempo, mais lento somos... Se ficarmos com o mouse segurado e parado em um ponto durante alguns segundos e soltar, o resultado será completamente diferente de arrastar rapidamente e soltar...regra de velocidade... Bom resumindo fiz mais um listener para desenhar uma linha pra ficar visivel o drag. Após isso vem o nosso evento de Release que é aonde soltamos o dedinho do mouse gravamos esse novo ponto para poder processar o calculo, gravamos o novo tempo em milisegundos para poder comparar também seria interessante tirar o calculo dai e colocar em uma função "calcular" ficaria esteticamente melhor... de qualquer forma, chegamos no nosso amigo calculo... é um conta simples como temos 2 eixos, vamos calcular o deltaX e deltaY aonde delta é apenas um sinonimo para "diferença" que eu estou usando...nada a ver em deltaX e segundo a minha formula que é (deltaDist / deltaTempo *constanteConcertoQuebraGalho ) teremos ai:
var deltaX:Number = ( deltaDistanceX / ( deltaTime * this.SpeedConstant ) );
caso alguen não conheça, pegamos a diferença em segundos, através da comparação entre 2 "times" provenientes da classe nativa Date, que nos fornece o método time(); que retorna o tempo em milisegundos com ponto zero em seja la quando, acho que 1970. Assim pudemos ver quanto tempo demoramos pra chegar de um ponto ao outro... Retiramos o nosso listener de update da Linha demonstrativa, pois não queremos mais um listener de ENTER_FRAME rodando sem parar a estoua... como nos foi passado uma array de objetos que serão afetados pelo movimento, fazemos um for each para distribuir o comando para todos, e enfim utilizando o nosso método setter de aceleração AccX e accY atualizamos nosso objetos de acordo com o nosso drag/drop. Agora, usando essas classes em um exemplo simples: Fiz um for para que vocês vissem que podemos colocar N objetos dependendo do quanto o processador aguentar...
import Dragable
import DeltaDrag

var objectsArray:Array = new Array();

for(var i:uint = 0; i< 20; i++){

var poofy:Dragable = new Dragable();

poofy.graphics.beginFill(0xff0000);
poofy.graphics.drawRect(0,0,100,100);
poofy.graphics.endFill();

poofy.x = 200*i;
poofy.y = 150;

stage.addChild(poofy);

objectsArray.push(poofy);

}

var myDragManager:DeltaDrag = new DeltaDrag(stage,objectsArray);

Bons estudos para os que leram até aqui, creio que, quem leu aprendeu e quem não leu, bom não perdeu nada, deixou de ganhar...

Abraços do Poofy

Link para o comentário
Compartilhar em outros sites

1 resposta a esta questão

Posts Recomendados

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152k
    • Posts
      651,8k
×
×
  • Criar Novo...