No ActionScript 3 não existe o duplicateMovieClip e a DisplayObject não implementa nenhum método de clone (espero que isso não dure muito). Ué, mas qual é o problema? É simples. As vezes não é necessária apenas uma nova instância de um objeto, mas uma que carregue consigo o estado do objeto original. Para isso serve (ou serviria) o método clone. Na prática, em um dado momento, elas são iguais e são diferentes. Isso quer dizer que elas possuem referência a endereços de memória distintos e se uma delas sofrer alteração a outra se manterá intacta. Ou seja, no momento em que a instância clone é criada ambas possuem o mesmo estado, mas não a mesma identidade.
Onde isso faz falta?
Suponha que você queira manter 2 imagens iguais aparecendo na tela para simular um efeito de espelho ou que você precise mostrar um thumb e uma imagem grande e esta imagem é carregada dinâmicamente. Você não pode simplesmente dar addChild uma segunda vez, pois o seu objeto vai se mover. Sim, ele vai sumir do lugar antigo e aparecer no novo lugar, mas por quê? Não era para ser uma referência na memória? Sim, continua sendo, mas… Todo DisplayObject possui uma propriedade parent que faz referência ao DisplayObjectContainer onde ele foi adicionado. Sempre que o método addChild é chamado o valor da propriedade parent é alterado e consequentemente o DisplayObject deixa de estar no lugar anterior, porque afinal de contas ele só tem um pai.
Para Bitmap felizmente existe um jeitinho, mas para outros DisplayObject, não. Mas o que um Bitmap tem de tão especial? Um objeto Bitmap tem em sua composição um objeto BitmapData, e este por sua vez tem o método clone implementado. É na propriedade bitmapData que estão armazenadas todas as características da imagem. Segue um exemplo com um Bitmap gerado pelo código, mais especificamente um quadrado vermelho, veja como é simples:
// criando um bitmap (quadrado) var bitmap:Bitmap = new Bitmap(new BitmapData(100, 100, false, 0xBB0000)); // adicionando bitmap no palco this.addChild(bitmap); // criando um novo bitmap com o clone do bitmap data var bitmapClone:Bitmap = new Bitmap(bitmap.bitmapData.clone()); // modificando o posicionamento p/ enxergarmos os 2 elementos bitmapClone.x = 100; bitmapClone.y = 100; // adicionando o clone no palco this.addChild(bitmapClone);
Se uma imagem é carregada dinamicamente o processo é exatamente o mesmo, já que todo objeto Bitmap possui em sua composição um BitmapData sendo ele carregado externamente ou não. Então aproveitamos o que a imagem já tem. Segue um exemplo:
// declara e instancia um objeto loader var loader:Loader = new Loader(); // adiciona listener para o carregmento da imagem loader.contentLoaderInfo.addEventListener(Event.COMPLETE, handleLoadComplete); // define uma url para carregamento var urlRequest:URLRequest = new URLRequest("http://www.nyan.com.br/ico/it.png"); // inicia o processo de carregamento loader.load(urlRequest); // handle para o evento de complete function handleLoadComplete(event:Event):void { // cria referencia para a imagem carregada var image:Bitmap = loader.content as Bitmap; // adiciona a imagem no palco this.addChild(image); // cria um novo bitmap e adiciona um clone // do BitmapData contido no Bitmap carregado var imageCopy:Bitmap = new Bitmap(image.bitmapData.clone()); // adicionando copia no palco this.addChild(imageCopy); // mudando posicionamento para enxergarmos imageCopy.x = 100; }
Tem mais uma coisa interessante nisso: se você declarar um novo Bitmap, atribuindo a ele um BitmapData existente mas sem chamar o método clone, também vai funcionar. A diferença é que se você fizer qualquer alteração no bitmapData através de qualquer um dos Bitmaps, ambos serão alterados, o que não acontece quando invocamos o método clone, pois ele sempre retorna uma nova instância. Este é um bom exemplo pra entender a diferença entre instâncias e referências.
Tags: bitmap, BitmapData, clone
Olá Daniela,
Achei seu site meio por acaso, pq busco na net mais explicações sobre OOP e AS3. Seu site é muito bom, muito bom mesmo e se todo conteúdo postado for assim, estou feito!
Bom, tenho vc no meu twitter (@tiagobraga), e estou sendo ligado no que vc está colocando no seu blog.
Você realmente está de parabéns!!!
Até
Daniela, queria saber se isto se aplica também a um MC, ja no palco, para duplicar ele ???
Oi Dieggo,
Se o método clone existisse em AS3 para
DisplayObject, seria possível “duplicar” qualquer elemento visual pelo simples fato de que, quando um elemento está no palco, significa que o estado dele está alterado e isso fica definido pela propriedadestagedo elemento. Então na hora de clonar o elemento a propriedadeparentestageseriam as mesmas.Quanto a este processo que descrevi aqui, funciona se o elemento estiver no palco sim, mas somente para bitmaps porque voce pode recuperar o bitmapData dele (e este possui o método
clone). Para MCs ainda não existe uma forma nativa de “duplicar”, mas já se fala em algumas bibliotecas para isso, porém ainda não testei nada do tipo.Um abraço.