Olá a todos. Veremos aqui como criar um menu circular em 3D personalizável. Utilizaremos alguns truques de matemática para simular a rotação em profundidade. Nada complicado. Mesmo quem não é fera em assuntos de cálculo conseguirá acompanhar o tutorial normalmente e projetar o menu como explicado.
Existem muitos menus na web com efeitos similares a esse, como por exemplo o site:
http://www.square-enix.co.jp/dvd/ff7ac/
[na parte de trailers]
http://www.square-enix.co.jp/dvd/ff7ac/
[na parte de trailers]
Essa URL foi submetida por um internauta ansioso em saber como se criava tal efeito. Em 3 passos seguintes, será mostrado como fazer algo similar.
Agenda (passos):
01. Introdução (esta página)
02. Criando o ambiente em Flash
03. Mecânica circular
04. Criando o ActionScript
01. Introdução (esta página)
02. Criando o ambiente em Flash
03. Mecânica circular
04. Criando o ActionScript
2º Passo: Criando o ambiente em Flash
2.1. Abra um novo arquivo com tamanho de projeto: 400 x 500
2.2. Crie botões para cada item de menu:
Veja que apenas coloquei um retângulo vermelho transparente no estado OVER do botão para dar efeito de destaque na foto. Para esse exemplo, criei 5 botões, embora você possa criar quantos quiser. O ActionScript se adapta ao número de botões.
2.3. Converta cada botão em um clipe de filme: selecione cada botão e aperte F8 para convertê-lo em um clipe de filme. Observe o ponto de registro:
2.4. Nomeie cada clipe recém criado no painel de propriedades
Nesse exemplo as instâncias receberam os nomes:
- embaixada
- goleiro
- disputa
- bola
- meiao
- embaixada
- goleiro
- disputa
- bola
- meiao
3º Passo: Mecânica Circular
Para criarmos o efeito ilusório em 3D de que o menu está girando e entrando em profundidade, iremos calcular as posições, transparências e tamanhos para cada botão do menu (encapsulado no respectivo clipe de filme). Podemos utilizar, da trigonometria, as funções para sabermos as posições X e Y em uma circunferência baseadas em um ângulo qualquer.
Para calcular as posições x e y do menu 1 por exemplo, temos:
x = cos * raio
y = sen * raio
x = cos * raio
y = sen * raio
Nesse caso, o Y realmente corresponderá a altura, entretanto o X não corresponderá a posição horizontal do menu, visto que na horizontal, todos os menus estarão na mesma posição. O que muda, para cada menu, é sua altura (Y) e a profundidade (mais perto do observador ou mais distante). Nada nos impede em converter o X calculado em Z (profundidade), é apenas uma outra forma de enxergar a fórmula.
Então, utilizaremos o X da equação para calcular o tamanho do menu (quanto menor, mais distante) e sua transparência (quanto mais transparente, mais distante).
É importante observar que cada botão de menu terá seu próprio ângulo, caso contrário, todos os botões estariam girando juntos na mesma posição.
Para podermos personalizar o menu, são criadas variáveis para regular toda a roda, como: valor do raio, transparência do item mais distante, transparência do item mais próximo, tamanho do item mais distante, tamanho do item mais próximo etc.
Para o giro, contamos com o deslocamento do mouse para cima e para baixo. Entretanto existe uma área de segurança no centro em que o mouse não rodará os menus para o usuário poder operar no botão com mais tranqüilidade.
Podemos agora olhar o código em ActionScript.
4º Passo: Criando o ActionScript
4.1. O seguinte trecho de código é colocado no primeiro quadro da linha de tempo principal
4.2. Para controlar a animação é utilizado o disparo freqüente do evento onEnterFrame da linha de tempo principal.
/*******************************************/ // variavies de configuracao /*******************************************/ // guardar as instancias a serem rotacionadas em um vetor var clips = Array("goleiro", "meiao", "disputa", "bola", "embaixada"); var raio = 150; // raio de rotacao var aceleracao = 0.05; // aceleracao do mouse para o giro var alphaMinimo = 20; // transparencia do botao de menu mais distante var alphaMaximo = 70; // transparencia do botao de menu mais proximo var escalaMinima = 50; // tamanho do botao de menu mais distante var escalaMaxima = 100; // tamanho do botao de menu mais distante var mouseSeguro = 100; // pixels em torno do centro nos quais o // mouse nao gira o menu /*******************************************/ // Variaveis calculadas /*******************************************/ // variacao da transparencia var difAlpha = alphaMaximo - alphaMinimo; // variacao do tamanho var difEscala = escalaMaxima - escalaMinima; // posicao central do menu em X e Y var xIni = Stage.width / 2; var yIni = Stage.height / 2; var dobroRaio = raio * 2; var conversao = Math.PI / 180; // fator de conversao de angulo para radiano var difAngular = 360 / clips.length; // diferenca angular entre os itens de menu var angulo = 0; // angulo inicial da roda como um todo /*******************************************/ // funcoes /*******************************************/ // funcao para determinar as posicoes X e Y // de um menu em funcao do angulo e do raio function posCircular(angulo, raio) { var pos = new Object(); var rad = angulo * conversao; pos.x = Math.sin(rad) * raio; pos.y = Math.cos(rad) * raio; return pos; } // funcao para ser chamada na mesma frequencia da animacao // e que eh responsavel por girar o menu this.onEnterFrame = function () { // calculamos se o mouse esta fora da area central // e com que velocidade o menu ira girar velocidade = (_root._ymouse - yIni) if (Math.abs(velocidade) <= mouseSeguro) velocidade = 0; else velocidade *= aceleracao; // giramos o menu todo angulo += velocidade; // reposicionamos cada item do menu for (i = 0; i < clips.length; i++) { // criar alias para o clipe de filme atual var ptr = _root[clips[i]]; // alterar posicao horizontal do menu ptr._x = xIni; // calcular a diferenca angular desse menu // em relacao a origem da roda ptr.difAngular = difAngular * i; // buscar as posicoes X (profundidade) e Y (altura) do menu var pos = posCircular(angulo + ptr.difAngular, raio); ptr._y = yIni + pos.y; // calcular percentual de afastamento do menu // para alterar seu tamanho e transparencia var perc = (pos.x + raio) / dobroRaio; ptr._alpha = perc * difAlpha + alphaMinimo; ptr._xscale = ptr._yscale = perc * difEscala + escalaMinima; // colocar o menu acima dos que estao mais afastados ptr.swapDepths(pos.x + dobroRaio); } } |
por: Thiago dos Santos Prado
Nenhum comentário:
Postar um comentário