Você está na página 1de 62

Machine Translated by Google

JavaFX
Transformações, animações e efeitos visuais

Lançamento 8

E50479-01

Março 2014

Este documento descreve transformações, animações de linha


do tempo e efeitos visuais disponíveis no JavaFX.
Machine Translated by Google

Transformações, animações e efeitos visuais JavaFX, versão 8

E50479-01

Copyright © 2011, 2014, Oracle e/ou suas afiliadas. Todos os direitos reservados.

Autor principal: Dmitry Kostovarov

Este software e a documentação relacionada são fornecidos sob um contrato de licença contendo restrições de uso e
divulgação e são protegidos por leis de propriedade intelectual. Exceto conforme expressamente permitido em seu contrato de
licença ou permitido por lei, você não pode usar, copiar, reproduzir, traduzir, transmitir, modificar, licenciar, transmitir, distribuir,
exibir, executar, publicar ou exibir qualquer parte, de qualquer forma, ou por qualquer meio.
A engenharia reversa, desmontagem ou descompilação deste software, a menos que exigido por lei para
interoperabilidade, é proibida.

As informações aqui contidas estão sujeitas a alterações sem aviso prévio e não são garantidas como isentas de erros. Se
você encontrar algum erro, informe-nos por escrito.

Se este for um software ou documentação relacionada entregue ao governo dos EUA ou a qualquer pessoa licenciando-o
em nome do governo dos EUA, o seguinte aviso é aplicável:

USUÁRIOS FINAIS DO GOVERNO DOS EUA: Os programas da Oracle, incluindo qualquer sistema operacional, software
integrado, quaisquer programas instalados no hardware e/ou documentação, entregues aos usuários finais do governo dos
EUA são "software de computador comercial" de acordo com o Regulamento de Aquisição Federal aplicável e agência-
regulamentos complementares específicos. Assim, o uso, duplicação, divulgação, modificação e adaptação dos programas,
incluindo qualquer sistema operacional, software integrado, quaisquer programas instalados no hardware e/ou documentação,
estará sujeito aos termos de licença e restrições de licença aplicáveis aos programas . Nenhum outro direito é concedido ao
governo dos EUA.

Este software ou hardware é desenvolvido para uso geral em uma variedade de aplicativos de gerenciamento de
informações. Ele não foi desenvolvido ou destinado ao uso em quaisquer aplicações inerentemente perigosas, incluindo
aplicações que possam criar risco de ferimentos pessoais. Se você usar este software ou hardware em aplicativos
perigosos, será responsável por tomar todas as medidas apropriadas de proteção contra falhas, backup, redundância e
outras medidas para garantir seu uso seguro. A Oracle Corporation e suas afiliadas se isentam de qualquer responsabilidade
por quaisquer danos causados pelo uso deste software ou hardware em aplicativos perigosos.

Oracle e Java são marcas registradas da Oracle e/ou de suas afiliadas. Outros nomes podem ser marcas registradas de seus
respectivos proprietários.

Intel e Intel Xeon são marcas comerciais ou marcas registradas da Intel Corporation. Todas as marcas comerciais SPARC
são usadas sob licença e são marcas comerciais ou marcas registradas da SPARC International, Inc. AMD, Opteron, o
logotipo AMD e o logotipo AMD Opteron são marcas comerciais ou marcas registradas da Advanced Micro Devices. UNIX é
uma marca registrada do The Open Group.

Este software ou hardware e documentação podem fornecer acesso ou informações sobre conteúdo, produtos e serviços de
terceiros. A Oracle Corporation e suas afiliadas não são responsáveis e se isentam expressamente de todas as garantias de
qualquer tipo com relação a conteúdo, produtos e serviços de terceiros. A Oracle Corporation e suas afiliadas não serão
responsáveis por quaisquer perdas, custos ou danos incorridos devido ao seu acesso ou uso de conteúdo, produtos ou
serviços de terceiros.
Machine Translated by Google

Conteúdo

Prefácio................................................. ................................................ ................................................ ............ v

Sobre este documento ....................................... ................................................ ............................. v


Público................................................. ................................................ ................................................ .. v

Acessibilidade à Documentação............................................ ................................................ ................... v Documentos


Relacionados ....................... ................................................ ................................................ ..... v
Convenções ....................................... ................................................ ............................................. v

Parte I Aplicando Transformações em JavaFX

1 Visão geral das transformações

Apresentando Transformações ........................................ ................................................ ................ 1-1

2 Tipos e exemplos de transformação


Tradução ................................................ ................................................ ................................................ 2- 1
Rotação................................................. ................................................ ................................................ ... 2-1

Escalonamento .................................................. ................................................ ................................................ ..... 2-2


Cisalhamento ....................................... ................................................ ................................................ .......... 2-3 Múltiplas
Transformações........................... ................................................ ......................................... 2-4 Arquivos de
aplicativos ......... ................................................ ................................................ ......................... 2-4

Parte II Criando transições e animações de linha de tempo

3 Noções básicas de animação

Transições ....................................... ................................................ ................................................ 3- 1


Transição Fade ....................................... ................................................ ......................................... 3-1
Transição de Caminho ....................................... ................................................ ......................................... 3-1
Transição Paralela ....................................... ................................................ .............................3-2

Transição Sequencial ....................................... ................................................ ......................3-3 Animação da linha do


tempo ............... ................................................ ................................................ ........... 3-4
Animação básica da linha do tempo ....................................... ................................................ ................3-4
Eventos da linha do tempo ....................................... ................................................ ................................3-5

Interpoladores ....................................... ................................................ ................................................ 3-7 Embutido em


Interpoladores ................................................. ................................................ ......................... 3-7 Interpoladores
personalizados ..................... ................................................ ................................................ ...3-7

iii
Machine Translated by Google

Arquivos de aplicativos ................................................. ................................................ ......................................... 3-8

4 Exemplo de Animação de Árvore


Projeto e Elementos .............................................. ................................................ ................................ 4-1
Grama .............. ................................................ ................................................ ......................................... 4-2

Criando Grama ....................................... ................................................ .........................................4-2 Criando animação


de linha de tempo para movimento de grama ..... ................................................ ................4-3
Árvore .............................. ................................................ ................................................ ............................. 4-4
Galhos ................................................. ................................................ .............................................4-4
Folhas e flores ....................................... ................................................ .............................4-6

Animando os elementos da árvore ....................................... ................................................ ..............4-6 Cultivando uma


árvore .................. ................................................ ................................................ 4-6 Criando o Movimento da Coroa
da Árvore ...................................... ................................................ ...4-7 Animando a mudança de
estação ....................................... ................................................ ..................4-8 Arquivos de
aplicativos ............................... ................................................ ................................................ ... 4-10

Parte III Criando efeitos visuais

5 Aplicando Efeitos
Efeito de Mistura ....................................... ................................................ ......................................... 5-1
Efeito Bloom ................................................. ................................................ ............................................. 5-2
Efeitos de desfoque .............................................. ................................................ ................................................ 5 -3
Borrão de caixa ................................................. ................................................ ......................................... 5-3
Desfoque de movimento ....................................... ................................................ ......................................... 5-4
Desfoque Gaussiano ....................................... ................................................ ......................................... 5-5

Efeito de sombra projetada .............................................. ................................................ ................................ 5-5 Efeito de


Sombra Interna .......... ................................................ ................................................ ................... 5-7
Reflexão ......................................................... ................................................ ................................................ 5 -8

Efeito de iluminação .................................................. ................................................ ......................................... 5-9 Efeito de


perspectiva .. ................................................ ................................................ ...................... 5-10 Criando uma Cadeia de
Efeitos............. ................................................ ................................................ .... 5-11 Arquivos de
Aplicativo ....................................... ................................................ ......................................... 5-13

Parte IV Código-fonte para as transformações, animações e efeitos visuais


Tutorial

A Xylophone.java

4
Machine Translated by Google

Prefácio

Este prefácio descreve os recursos e convenções de acessibilidade do documento usados neste


tutorial - Transformações, Animações e Efeitos Visuais.

Sobre este documento


Este tutorial descreve transformações, animações de linha de tempo e efeitos visuais
disponíveis no JavaFX.

Público
Este documento destina-se a desenvolvedores JavaFX.

Acessibilidade da Documentação
Para obter informações sobre o compromisso da Oracle com a acessibilidade, visite
o site do Programa de Acessibilidade da Oracle em http://www.oracle.com/pls/topic/
lookup?ctx=acc&id=docacc.

Acesso ao Suporte Oracle


Os clientes Oracle têm acesso ao suporte eletrônico por meio do My Oracle Support. Para obter
informações, visite http://www.oracle.com/pls/topic/lookup?ctx=acc&id=info ou visite http://
www.oracle.com/pls/topic/lookup?ctx=acc&id=trs se você são deficientes auditivos.

Documentos relacionados
Para obter mais informações, consulte os seguintes documentos no conjunto de documentação

do JavaFX: ÿ Introdução ao JavaFX

Convenções
As seguintes convenções de texto são usadas neste documento:

Convenção Significado

negrito O tipo negrito indica elementos gráficos da interface do usuário associados a uma
ação ou termos definidos no texto ou no glossário.

v
Machine Translated by Google

Convenção Significado

itálico O tipo itálico indica títulos de livro, ênfase ou variáveis de espaço reservado para os
quais você fornece valores específicos.

monoespaço O tipo monoespaçado indica comandos dentro de um parágrafo, URLs, código em


exemplos, texto que aparece na tela ou texto que você insere.

vi
Machine Translated by Google

Parte I
Parte IAplicando transformações no JavaFX

Este tutorial descreve as transformações suportadas no JavaFX e contém os seguintes capítulos:

ÿ Visão geral das transformações

ÿ Tipos e exemplos de transformação


Machine Translated by Google
Machine Translated by Google

1
1Visão Geral das Transformações

Este capítulo apresenta as transformações suportadas no JavaFX.

Todas as transformações estão localizadas no pacote javafx.scene.transform e são


subclasses da classe Transform .

Apresentando Transformações
Uma transformação muda o lugar de um objeto gráfico em um sistema de coordenadas
de acordo com certos parâmetros. Os seguintes tipos de transformações são suportados no
JavaFX:
ÿ Tradução

ÿ Rotação

Dimensionamento ÿ Distorção Essas transformações podem ser aplicadas a um nó


autônomo ou a grupos de nós. Você pode aplicar uma transformação por vez ou pode
combinar transformações e aplicar várias transformações a um nó.

A classe Transform implementa os conceitos de transformações afins. A classe Affine estende


a classe Transform e atua como uma superclasse para todas as transformações. As transformações
afins são baseadas na álgebra euclidiana e realizam um mapeamento linear (através do uso de
matrizes) das coordenadas iniciais para outras coordenadas, preservando a retidão e o paralelismo
das linhas. Transformações afins podem ser construídas usando rotações, translações, escalas e
cisalhamentos observableArrayLists.

Nota: Normalmente, não use a classe Affine diretamente, mas, em vez disso,
use as transformações específicas Translate, Scale, Rotate ou Shear.

As transformações no JavaFX podem ser executadas ao longo de três coordenadas, permitindo


assim que os usuários criem objetos e efeitos tridimensionais (3-D). Para gerenciar a exibição
de objetos com profundidade em gráficos 3D, o JavaFX implementa z-buffering. O Z-buffering
garante que a perspectiva seja a mesma no mundo virtual e no real: um objeto sólido em
primeiro plano bloqueia a visão de outro atrás dele. Z-buffering pode ser ativado usando a
classe setDepthTest . Você pode tentar desativar o z-buffer (setDepthTest(DepthTest.DISABLE))
no aplicativo de amostra para ver o efeito do z-buffer.

Para simplificar o uso da transformação, JavaFX implementa construtores de transformação


com os eixos x e y juntamente com os eixos x, y e z. Se você deseja criar um

Visão geral das transformações 1-1


Machine Translated by Google

Apresentando Transformações

efeito bidimensional (2-D), você pode especificar apenas as coordenadas x e y. Se você deseja
criar um efeito 3D, especifique todas as três coordenadas.

Para poder ver objetos 3-D e efeitos de transformação no JavaFX, os usuários devem habilitar
a câmera em perspectiva.

Embora conhecer os conceitos subjacentes possa ajudá-lo a usar o JavaFX com mais eficiência,
você pode começar a usar as transformações estudando o exemplo fornecido com este
documento e tentando diferentes parâmetros de transformação. Para obter mais informações
sobre classes, métodos ou recursos adicionais específicos, consulte a documentação da API.

Neste documento, um aplicativo Xylophone é usado como exemplo para ilustrar todas as
transformações disponíveis. Você pode baixar seu código-fonte clicando no link
transforms.zip.

Figura 1–1 Um aplicativo de xilofone

1-2 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google

2
2 Tipos e Exemplos de Transformação

Este documento descreve transformações específicas e fornece exemplos de código.

Tradução
A transformação de translação desloca um nó de um lugar para outro ao longo de um dos eixos
em relação à sua posição inicial. A posição inicial da barra do xilofone é definida pelas
coordenadas x, y e z. No Exemplo 2–1, os valores de posição inicial são especificados pelas
variáveis xStart, yPos e zPos . Algumas outras variáveis são adicionadas para simplificar os
cálculos ao aplicar diferentes transformações. Cada compasso do xilofone é baseado em um
dos compassos de base. O exemplo então traduz as barras de base com diferentes
deslocamentos ao longo dos três eixos para localizá-los corretamente no espaço.

O exemplo 2–1 mostra um trecho de código do aplicativo de amostra com a transformação


de tradução.

Exemplo 2–1 Tradução


Grupo retânguloGrupo = new Grupo();
retânguloGroup.setDepthTest(DepthTest.ENABLE);

duplo xStart = 260,0;


duplo xOffset = 30,0;
duplo yPos = 300,0; duplo
zPos = 0,0;
largura da barra dupla = 22,0;
double barDepth = 7,0;

// Base1
Cubo base1Cube = new Cube(1.0, new Color(0.2, 0.12, 0.1, 1.0), 1.0); base1Cube.setTranslateX(xStart
+ 135); base1Cube.setTranslateZ(yPos+20.0); base1Cube.setTranslateY(11.0);

Rotação
A transformação de rotação move o nó em torno de um ponto de pivô especificado da
cena. Você pode usar o método rotate da classe Transform para executar a rotação.

Para girar a câmera em torno do xilofone no aplicativo de amostra, a transformação de


rotação é usada, embora tecnicamente seja o próprio xilofone que se move quando o mouse
gira a câmera.

Tipos de Transformação e Exemplos 2-1


Machine Translated by Google

Dimensionamento

O exemplo 2–2 mostra o código para a transformação de rotação.

Exemplo 2–2 Rotação


classe Cam estende Grupo {
Traduzir t = new Traduzir();
Traduzir p = new Traduzir();
Traduzir ip = new Traduzir();
Girar rx = new Girar();
{ rx.setAxis(Girar.X_AXIS); }
Girar ry = new Girar();
{ ry.setAxis(Girar.Y_AXIS); }
Girar rz = new Girar();
{ rz.setAxis(Girar.Z_AXIS); }
Escala s = new Escala(); public
Cam() { super(); getTransforms().addAll(t, p, rx, rz, ry, s, ip); }
}
...
cena.setOnMouseDragged(new EventHandler<MouseEvent>() {
public void handle(MouseEvent me) { mouseOldX =
mousePosX; mouseVelhoY = mousePosY;

mousePosX = me.getX();
mousePosY = me.getY();
mouseDeltaX = mousePosX - mouseOldX;
mouseDeltaY = mousePosY - mouseOldY; if
(me.isAltDown() && me.isShiftDown() &&
me.isPrimaryButtonDown())
{ cam.rz.setAngle(cam.rz.getAngle() - mouseDeltaX);
}
else if (me.isAltDown() && me.isPrimaryButtonDown())
{ cam.ry.setAngle(cam.ry.getAngle() - mouseDeltaX);
cam.rx.setAngle(cam.rx.getAngle() + mouseDeltaY);
}
else if (me.isAltDown() && me.isSecondaryButtonDown()) {
escala dupla = cam.s.getX(); double
newScale = escala + mouseDeltaX*0.01;
cam.s.setX(novaEscala); cam.s.setY(novaEscala);
cam.s.setZ(novaEscala);
}
else if (me.isAltDown() && me.isMiddleButtonDown()) {
cam.t.setX(cam.t.getX() + mouseDeltaX);
cam.t.setY(cam.t.getY() + mouseDeltaY);
}
}
});

Observe que o ponto de pivô e o ângulo definem o ponto de destino para o qual a imagem é
movida. Calcule cuidadosamente os valores ao especificar o ponto de pivô. Caso contrário, a imagem
pode aparecer onde não deveria estar. Para obter mais informações, consulte a documentação da API.

Dimensionamento

A transformação de dimensionamento faz com que um nó pareça maior ou menor, dependendo do fator
de dimensionamento. A escala altera o nó para que as dimensões ao longo de seus eixos sejam
multiplicadas pelo fator de escala. Semelhante às transformações de rotação, as transformações de
dimensionamento são aplicadas em um ponto pivô. Esse ponto de pivô é considerado o ponto em torno
do qual ocorre o escalonamento.

2-2 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google

Tosquia

Para dimensionar, use a classe Scale e o método scale da classe Transform .

No aplicativo Xylophone, você pode dimensionar o xilofone usando o mouse enquanto pressiona Alt
e o botão direito do mouse. A transformação de escala é usada para ver a escala.

O exemplo 2–3 mostra o código para a transformação de escala.

Exemplo 2–3 Escala


else if (me.isAltDown() && me.isSecondaryButtonDown()) {
escala dupla = cam.s.getX(); double
newScale = escala + mouseDeltaX*0.01;
cam.s.setX(novaEscala); cam.s.setY(novaEscala); cam.s.setZ(novaEscala);
}
...

Tosquia
Uma transformação de cisalhamento gira um eixo para que o eixo x e o eixo y não sejam mais
perpendiculares. As coordenadas do nó são deslocadas pelos multiplicadores especificados.

Para cortar, use a classe Shear ou o método shear da classe Transform .

No aplicativo Xilofone, você pode cortar o xilofone arrastando o mouse enquanto mantém pressionada
a tecla Shift e pressionando o botão esquerdo do mouse.

Figura 2–1 Transformação de cisalhamento

O exemplo 2–4 mostra o trecho de código para a transformação de cisalhamento.

Exemplo 2–4 Cisalhamento


else if (me.isShiftDown() && me.isPrimaryButtonDown()) {
double yShear = shear.getY();
shear.setY(yShear + mouseDeltaY/1000.0); double xShear
= shear.getX(); shear.setX(xShear + mouseDeltaX/1000.0);

Tipos de Transformação e Exemplos 2-3


Machine Translated by Google

Múltiplas Transformações

Múltiplas Transformações Você


pode construir múltiplas transformações especificando uma cadeia ordenada de
transformações. Por exemplo, você pode dimensionar um objeto e, em seguida, aplicar
uma transformação de distorção a ele ou pode transladar um objeto e dimensioná-lo.

O exemplo 2–5 mostra várias transformações aplicadas a um objeto para criar uma barra de
xilofone.

Exemplo 2–5 Transformações Múltiplas


Cubo base1Cube = new Cube(1.0, new Color(0.2, 0.12, 0.1, 1.0), 1.0); base1Cube.setTranslateX(xStart
+ 135);
base1Cube.setTranslateZ(yPos+20.0);
base1Cube.setTranslateY(11.0);
base1Cube.setScaleX(barWidth*11.5);
base1Cube.setScaleZ(10.0);
base1Cube.setScaleY(barDepth*2.0);

Arquivos de aplicativos
Código fonte

ÿ Xilofone.java

Projetos NetBeans ÿ

transformações.zip

2-4 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google

parte II
Parte IICriando Transições e Linha do Tempo
Animações

Este tutorial contém informações que você pode usar para criar animação em JavaFX e contém os capítulos a
seguir.

Animation Basics fornece conceitos básicos de animação e contém as seguintes partes:

ÿ Transições

ÿ Animação da linha do tempo

ÿ Interpoladores O

capítulo Tree Animation Example contém uma descrição do exemplo Tree Animation e fornece algumas
dicas e truques sobre animação em JavaFX.
Machine Translated by Google
Machine Translated by Google

3
3 Noções básicas de animação

A animação em JavaFX pode ser dividida em animação de linha do tempo e transições. Este capítulo fornece
exemplos de cada tipo de animação.

Timeline e Transition são subclasses da classe javafx.animation.Animation .


Para obter mais informações sobre classes, métodos ou recursos adicionais específicos, consulte a documentação da API.

Transições
As transições em JavaFX fornecem os meios para incorporar animações em uma linha de tempo interna. As
transições podem ser compostas para criar várias animações que são executadas em paralelo ou sequencialmente.
Consulte as seções Transição Paralela e Transição Sequencial para obter detalhes. As seções a seguir fornecem alguns
exemplos de animação de transição.

Transição Fade

Uma transição de esmaecimento altera a opacidade de um nó em um determinado momento.

O exemplo 3–1 mostra um trecho de código para uma transição de esmaecimento aplicada a um retângulo.
Primeiro, um retângulo com cantos arredondados é criado e, em seguida, uma transição de esmaecimento é aplicada a
ele.

Exemplo 3–1 Transição Fade

final Rectangle rect1 = new Rectangle(10, 10, 100, 100);


rect1.setArcHeight(20); rect1.setArcWidth(20); rect1.setFill(Color.RED);

...
FadeTransition ft = new FadeTransition(Duration.millis(3000), rect1); ft.setFromValue(1.0);
ft.setToValue(0.1); ft.setCycleCount(Timeline.INDEFINITE); ft.setAutoReverse(true); ft.play();

Transição de caminho

Uma transição de caminho move um nó ao longo de um caminho de uma extremidade à outra em um determinado
tempo.

Noções básicas de animação 3-1


Machine Translated by Google
Transições

Figura 3–1 Transição de caminho

O exemplo 3–2 mostra um trecho de código para uma transição de caminho aplicada a um retângulo.
A animação é invertida quando o retângulo atinge o final do caminho. No código, primeiro é criado um
retângulo com cantos arredondados e, em seguida, uma nova animação de caminho é criada e aplicada
ao retângulo.

Exemplo 3–2 Transição de caminho

final Rectangle rectPath = new Rectangle (0, 0, 40, 40); rectPath.setArcHeight(10);


rectPath.setArcWidth(10); rectPath.setFill(Color.ORANGE);

...
Caminho caminho = new
Caminho(); path.getElements().add(new MoveTo(20,20));
path.getElements().add(new CubicCurveTo(380, 0, 380, 120, 200, 120)); path.getElements().add(new
CubicCurveTo(0, 120, 0, 240, 380, 240)); PathTransition pathTransition = new PathTransition();
pathTransition.setDuration(Duration.millis(4000)); pathTransition.setPath(caminho);
pathTransition.setNode(rectPath);
pathTransition.setOrientation(PathTransition.OrientationType.ORTHOGONAL_TO_ TANGENT);
pathTransition.setCycleCount(Timeline.INDEFINITE); pathTransition.setAutoReverse(true);
pathTransition.play();

Transição Paralela
Uma transição paralela executa várias transições simultaneamente.

O exemplo 3–3 mostra o trecho de código para a transição paralela que executa as transições de
fade, translação, rotação e dimensionamento aplicadas a um retângulo.

Figura 3–2 Transição Paralela

Exemplo 3–3 Transição Paralela

Rectangle rectParallel = new Rectangle(10,200,50, 50);

3-2 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google
Transições

rectParallel.setArcHeight(15);
rectParallel.setArcWidth(15);
rectParallel.setFill(Color.DARKBLUE);
rectParallel.setTranslateX(50);
rectParallel.setTranslateY(75);
...
FadeTransition fadeTransition =
new FadeTransition(Duration.millis(3000), rectParallel);
fadeTransition.setFromValue(1.0f);
fadeTransition.setToValue(0.3f);
fadeTransition.setCycleCount(2);
fadeTransition.setAutoReverse(true);
TranslateTransition translateTransition =
new TranslateTransition(Duration.millis(2000), rectParallel);
translateTransition.setFromX(50);
translateTransition.setToX(350);
translateTransition.setCycleCount(2);
translateTransition.setAutoReverse(true); RotateTransition
rotateTransition =
novo RotateTransition(Duration.millis(3000), rectParallel);
rotaTransition.setByAngle(180f);
rotaTransition.setCycleCount(4);
rotaTransition.setAutoReverse(true);
ScaleTransition scaleTransition =
new ScaleTransition(Duration.millis(2000), rectParallel);
scaleTransition.setToX(2f);
scaleTransition.setToY(2f);
scaleTransition.setCycleCount(2);
scaleTransition.setAutoReverse(true);

parallelTransition = new ParallelTransition();


parallelTransition.getChildren().addAll(
fadeTransition,
translateTransition,
rotateTransition,
scaleTransition
);
parallelTransition.setCycleCount(Timeline.INDEFINITE); parallelTransition.play();

Transição sequencial
Uma transição sequencial executa várias transições uma após a outra.
O exemplo 3–4 mostra o código para a transição sequencial que é executada uma após a
outra. Esmaecer, traduzir, girar e dimensionar as transições que são aplicadas a um retângulo.

Exemplo 3–4 Transição sequencial


Rectangle rectSeq = new Rectangle(25,25,50,50);
rectSeq.setArcHeight(15); rectSeq.setArcWidth(15);
rectSeq.setFill(Color.CRIMSON); rectSeq.setTranslateX(50);
rectSeq.setTranslateY(50);

...

FadeTransition fadeTransition =
new FadeTransition(Duration.millis(1000), rectSeq);

Noções básicas de animação 3-3


Machine Translated by Google
Animação da linha do tempo

fadeTransition.setFromValue(1.0f);
fadeTransition.setToValue(0.3f);
fadeTransition.setCycleCount(1);
fadeTransition.setAutoReverse(true);

TranslateTransition translateTransition =
new TranslateTransition(Duration.millis(2000), rectSeq);
translateTransition.setFromX(50);
translateTransition.setToX(375);
translateTransition.setCycleCount(1);
translateTransition.setAutoReverse(true);

RotateTransition rotateTransition =
novo RotateTransition(Duration.millis(2000), rectSeq);
rotaTransition.setByAngle(180f); rotaTransition.setCycleCount(4);
rotaTransition.setAutoReverse(true);

ScaleTransition scaleTransition =
novo ScaleTransition(Duration.millis(2000), rectSeq);
scaleTransition.setFromX(1);
scaleTransition.setFromY(1);
scaleTransition.setToX(2);
scaleTransition.setToY(2);
scaleTransition.setCycleCount(1);
scaleTransition.setAutoReverse(true);

SequentialTransition = new SequentialTransition();


sequencialTransition.getChildren().addAll(
fadeTransition,
translateTransition,
rotateTransition,
scaleTransition);
sequencialTransition.setCycleCount(Timeline.INDEFINITE);
sequencialTransition.setAutoReverse(true);

sequencialTransition.play();

Para obter mais informações sobre animação e transições, consulte a documentação da API e a
seção Animação no projeto Ensemble no SDK.

Animação da linha do tempo

Uma animação é orientada por suas propriedades associadas, como tamanho, localização e cor,
etc. A linha de tempo fornece a capacidade de atualizar os valores de propriedade ao longo da
progressão do tempo. JavaFX suporta animação de quadro-chave. Na animação de quadro-
chave, as transições de estado animadas da cena gráfica são declaradas por instantâneos
iniciais e finais (quadros-chave) do estado da cena em determinados momentos. O sistema pode
executar automaticamente a animação. Ele pode parar, pausar, retomar, reverter ou repetir o
movimento quando solicitado.

Animação básica da linha do tempo

O código no Exemplo 3–5 anima um retângulo horizontalmente e o move de sua posição


original X=100 para X=300 em 500 ms. Para animar um objeto horizontalmente, altere as
coordenadas x e deixe as coordenadas y inalteradas.

3-4 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google
Animação da linha do tempo

Figura 3–3 Movimento horizontal

O exemplo 3–5 mostra o trecho de código para a animação básica da linha de tempo.

Exemplo 3–5 Animação da linha do tempo

final Rectangle rectBasicTimeline = new Rectangle(100, 50, 100, 50);


rectBasicTimeline.setFill(Color.RED);
...
final Timeline timeline = new Timeline();
timeline.setCycleCount(Timeline.INDEFINITE); linha do
tempo.setAutoReverse(true); valor-chave final kv = novo
valor-chave(rectBasicTimeline.xProperty(), 300); KeyFrame final kf = new
KeyFrame(Duration.millis(500), kv); linha do tempo.getKeyFrames().add(kf); timeline.play();

Eventos da linha do tempo

O JavaFX fornece os meios para incorporar eventos que podem ser acionados durante a reprodução
da linha do tempo. O código no Exemplo 3–6 altera o raio do círculo no intervalo especificado e KeyFrame
aciona a transição aleatória do círculo na coordenada x da cena.

Exemplo 3–6 Eventos da Linha do Tempo

importar javafx.application.Application; importar


javafx.stage.Stage; importar
javafx.animation.AnimationTimer; importar
javafx.animation.KeyFrame; importar
javafx.animation.KeyValue; importar
javafx.animation.Timeline; importar
javafx.event.ActionEvent; importar
javafx.event.EventHandler; importar
javafx.scene.Group; importar javafx.scene.Scene;
importar javafx.scene.effect.Lighting; importar
javafx.scene.layout.StackPane; importar
javafx.scene.paint.Color; importar
javafx.scene.shape.Circle; importar
javafx.scene.text.Text; importar javafx.util.Duration;

public class TimelineEvents extends Application {

//linha do tempo
principal private Linha do tempo linha
do tempo; temporizador AnimationTimer privado;

//variável para armazenar o quadro atual private


Integer i=0;

Noções básicas de animação 3-5


Machine Translated by Google
Animação da linha do tempo

@Override public void start(Stage stage) { Group p = new Group();


Cena cena = nova Cena(p); palco.setScene(cena);
palco.setWidth(500); palco.setHeight(500); p.setTranslateX(80);
p.setTranslateY(80);

//cria um círculo com efeito


final Circle circle = new Circle(20, Color.rgb(156,216,255)); circle.setEffect(new Lighting()); //cria um
texto dentro de um círculo

final Text text = new Text (i.toString()); text.setStroke(Color.BLACK); //


cria um layout para círculo com texto dentro do StackPane final
stack = new StackPane();

stack.getChildren().addAll(círculo, texto); pilha.setLayoutX(30);


pilha.setLayoutY(30);

p.getChildren().add(stack); palco.show();

//cria uma linha do tempo para mover o círculo timeline = new


Timeline();
timeline.setCycleCount(Timeline.INDEFINITE); linha do
tempo.setAutoReverse(true);

//Você pode adicionar uma ação específica quando cada quadro é iniciado.
timer = new AnimationTimer() {
@Sobrepor
public void handle(long l) {
text.setText(i.toString()); i++;

};

//cria um keyValue com fábrica: dimensionando o círculo 2 vezes KeyValue keyValueX = new
KeyValue(stack.scaleXProperty(), 2); KeyValue keyValueY = new KeyValue(stack.scaleYProperty(),
2);

//cria um keyFrame, o keyValue é atingido no tempo 2s Duration duration =


Duration.millis(2000); //pode-se adicionar uma ação específica quando o quadro-chave é
atingido EventHandler onFinished = new EventHandler<ActionEvent>() {

public void handle(ActionEvent t) {


stack.setTranslateX(java.lang.Math.random()*200-100); //Reiniciar contador

i = 0;
}
};

KeyFrame keyFrame = new KeyFrame(duração, onFinished , keyValueX, keyValueY);

//adiciona o quadro-chave à linha do tempo


timeline.getKeyFrames().add(keyFrame);

timeline.play();

3-6 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google

Interpoladores

timer.start();
}

public static void main(String[] args) { Application.launch(args);

}
}

Interpoladores A
interpolação define as posições do objeto entre os pontos inicial e final do movimento.
Você pode usar várias implementações integradas da classe Interpolator ou pode
implementar seu próprio Interpolator para obter um comportamento de interpolação personalizado.

Interpoladores embutidos
O JavaFX fornece vários interpoladores embutidos que você pode usar para criar diferentes
efeitos em sua animação. Por padrão, JavaFX usa interpolação linear para calcular as coordenadas.

O exemplo 3–7 mostra um trecho de código onde a instância do interpolador EASE_BOTH é


adicionada ao KeyValue na animação básica da linha do tempo. Este interpolador cria um
efeito de mola quando o objeto atinge seu ponto inicial e seu ponto final.

Exemplo 3–7 Interpolador embutido


final Rectangle rectBasicTimeline = new Rectangle(100, 50, 100, 50); rectBasicTimeline.setFill(Color.BROWN);

...
final Timeline timeline = new Timeline();
timeline.setCycleCount(Timeline.INDEFINITE); linha do
tempo.setAutoReverse(true); Valor-chave final kv = novo Valor-
chave(rectBasicTimeline.xProperty(), 300,
Interpolator.EASE_BOTH);
KeyFrame final kf = new KeyFrame(Duration.millis(500), kv); linha do tempo.getKeyFrames().add(kf);
timeline.play();

Interpoladores
personalizados Além dos interpoladores integrados, você pode implementar seu próprio interpolador
para obter um comportamento de interpolação personalizado. Um exemplo de interpolador
customizado consiste em dois arquivos java. O exemplo 3–8 mostra um interpolador personalizado
usado para calcular a coordenada y para a animação. O exemplo 3–9 mostra o trecho de código da
animação em que o AnimationBooleanInterpolator é usado.

Exemplo 3–8 Interpolador personalizado


public class AnimationBooleanInterpolator extends Interpolator {
@Sobrepor
curva dupla protegida(duplo t) { return Math.abs(0,5-
t)*2 ;
}
}

Exemplo 3–9 Animação com interpolador personalizado

Noções básicas de animação 3-7


Machine Translated by Google

Arquivos de aplicativos

final KeyValue keyValue1 = new KeyValue(rect.xProperty(), 300);


AnimationBooleanInterpolator yInterp = new AnimationBooleanInterpolator(); final KeyValue
keyValue2 = new KeyValue(rect.yProperty(), 0., yInterp);

Arquivos de aplicativos
Projetos NetBeans
ÿ animações.zip

3-8 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google

4
Exemplo de Animação 4Tree

Este capítulo fornece detalhes sobre o exemplo de animação de árvore. Você aprenderá como
todos os elementos da cena foram criados e animados.

A Figura 4–1 mostra a cena com uma árvore.

Figura 4–1 Animação da árvore

Projeto e Elementos
O projeto Tree Animation consiste em vários arquivos. Cada elemento, como folhas, folhas de
grama e outros, são criados em classes separadas. A classe TreeGenerator cria uma árvore de
todos os elementos. A classe Animator contém todas as animações, exceto a animação de grama
que reside na classe GrassWindAnimation .

A cena no exemplo contém os seguintes elementos:


ÿ Árvore com galhos, folhas e flores

ÿ Grama

Cada elemento é animado à sua maneira. Algumas animações são executadas em paralelo e outras são
executadas sequencialmente. A animação de crescimento da árvore é executada apenas uma vez, enquanto a
animação de mudança de estação é definida para ser executada infinitamente.

Exemplo de animação de árvore 4-1


Machine Translated by Google

Grama

Figura 4–2 Linha do tempo da animação

A animação de mudança de estação inclui as seguintes


partes: ÿ Folhas e flores aparecem na árvore ÿ Pétalas de
flores caem e desaparecem ÿ Folhas e grama mudam de
cor ÿ Folhas caem no chão e desaparecem

Grama
Esta seção descreve como a grama é criada e animada.

Criando grama
No exemplo de animação de árvore, a grama, mostrada na Figura 4–3 , consiste em
lâminas de grama separadas, cada uma das quais é criada usando Path e adicionada
à lista. Cada lâmina é então curvada e colorida. Um algoritmo é usado para
randomizar a altura, a curva e a cor das lâminas e distribuí-las no "solo". Você pode
especificar o número de lâminas e o tamanho do "solo" coberto com grama.

Figura 4–3 Grama

Exemplo 4–1 Criando uma lâmina de grama


public class Blade estende Path {

public final Color SPRING_COLOR = Color.color(random() * 0.5, random() * 0.5


+ 0,5, 0.).mais escuro();
public final Color AUTUMN_COLOR = Color.color(random() * 0.4 + 0.3, random() * 0.1 + 0.4, random() * 0.2);
largura dupla estática final privada = 3; private double x = RandomUtil.getRandom(170); private double y =
RandomUtil.getRandom(20) + 20; private double h = (50 * 1,5 - y / 2) * RandomUtil.getRandom(0,3); public
SimpleDoubleProperty phase = new SimpleDoubleProperty();

lâmina pública() {

4-2 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google

Grama

getElements().add(new MoveTo(0, 0)); final QuadCurveTo


curve1; final QuadCurveTo curve2; getElements().add(curve1
= new QuadCurveTo(-10, h, h / 4, h));
getElements().add(curve2 = new QuadCurveTo(-10, h, width, 0));

setFill(AUTUMN_COLOR); //cor de outono da lâmina setStroke(null);

getTransforms().addAll(Transform.translate(x, y));

curve1.yProperty().bind(new DoubleBinding() {

{
super.bind(curve1.xProperty());
}

@Sobrepor
protegido double computeValue() {

final duplo xx0 = curva1.xProperty().get(); return Math.sqrt(h * h - xx0 *


xx0);
}
}); //caminho do topo da lâmina é circular

//código para dobrar a lâmina


curve1.controlYProperty().bind(curve1.yProperty().add(-h / 4));
curve2.controlYProperty().bind(curve1.yProperty().add(-h / 4));

curve1.xProperty().bind(new DoubleBinding() {

rand duplo final = RandomUtil.getRandom(PI / 4);

{
super.bind(fase);
}

@Sobrepor
protegido double computeValue() {
return (h/4) + ((cos(phase.get() + (x + 400.) * PI/1600 +
rand) + 1) / 2.) * (-3. / 4) * h;
}
});
}
}

Criando animação da linha do tempo para o movimento da


grama A animação da linha do tempo que altera a coordenada x do topo da lâmina é usada
para criar o movimento da grama.

Vários algoritmos são usados para fazer o movimento parecer natural. Por exemplo, o topo de
cada lâmina é movido em um círculo em vez de uma linha reta, e a curva lateral da lâmina faz
com que pareça que ela se dobra com o vento. Números aleatórios são adicionados para
separar cada movimento da lâmina.

Exemplo 4–2 Animação de grama

classe GrassWindAnimation estende Transição {

Exemplo de animação de árvore 4-3


Machine Translated by Google

Árvore

final private Duração animationTime = Duration.seconds(3); fase DoubleProperty privada final =


new SimpleDoubleProperty(0); final private Timeline tl = new Timeline(Animation.INDEFINITE);

public GrassWindAnimation(List<Blade> lâminas) {

setCycleCount(Animation.INDEFINITE);
setInterpolator(Interpolator.LINEAR);
setCycleDuration(animationTime); for (Lâmina: lâminas) {

lâmina.fase.bind(fase);
}
}

@Sobrepor
interpolação nula protegida(fração dupla) { phase.set(frac * 2 * PI);

}
}

Árvore

Esta seção explica como a árvore mostrada na Figura 4–4 é criada e animada.

Figura 4–4 Árvore

Galhos
A árvore consiste em galhos, folhas e flores. Folhas e flores são desenhadas nos
galhos superiores da árvore. Cada geração de ramificação consiste em três ramificações
(uma ramificação superior e duas laterais) extraídas de uma ramificação pai. Você pode
especificar o número de gerações no código usando o NUMBER_OF_BRANCH_GENERATIONS
passado no construtor de TreeGenerator na classe Main. O exemplo 4–3 mostra o código
na classe TreeGenerator que cria o tronco da árvore (ou o ramo raiz) e adiciona três ramos
para as gerações seguintes.

4-4 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google

Árvore

Exemplo 4–3 Ramificação raiz

private List<Branch> generateBranches(Branch parentBranch, int depth) {


List<Branch> branches = new ArrayList<>(); if (parentBranch
== null) { // adiciona ramificação raiz
branches.add(new Branch());
} outro {
if (parentBranch.length < 10) {
return Coleções.emptyList();
}
branches.add(new Branch(parentBranch, Type.LEFT, depth)); branches.add(new
Branch(parentBranch, Type.RIGHT, depth)); branches.add(new Branch(parentBranch,
Type.TOP, depth));
}

ramos de retorno;
}
Para tornar a árvore mais natural, cada ramificação da geração filha cresce em um ângulo em
relação à ramificação pai, e cada ramificação filho é menor que a pai. O ângulo da criança é
calculado usando valores aleatórios. O exemplo 4–4 fornece um código para criar ramificações
filhas.

Exemplo 4–4 Ramificações filhas

public Branch(Branch parentBranch, tipo de tipo, int depth) {


esse();
SimpleDoubleProperty locAngle = new SimpleDoubleProperty(0);
globalAngle.bind(locAngle.add(parentBranch.globalAngle.get())); duplo transY = 0;

interruptor (tipo)
{ caixa TOP:
transY = parentBranch.length; comprimento
= parentBranch.length * 0,8;
locAngle.set(getRandom(10)); quebrar;

caso ESQUERDA:

caso DIREITA:
transY = parentBranch.length - getGaussianRandom(0,
parentBranch.length, parentBranch.length / 10, parentBranch.length / 10);
locAngle.set(getGaussianRandom(35, 10) * (Type.LEFT == type ? 1 :
-1));
if ((0 > globalAngle.get() || globalAngle.get() > 180) && profundidade <
4) {
length = parentBranch.length * getGaussianRandom(0.3, 0.1); } outro {

comprimento = parentBranch.length * 0,6;


}
quebrar;
}
setTranslateY(transY);
getTransforms().add(new Rotate(locAngle.get(), 0, 0)); globalH = getTranslateY()
* cos(PI / 2 - parentBranch.globalAngle.get() *
PI / 180) + parentBranch.globalH;
setBranchStyle(profundidade);
addChildToParent(parentBranch, this);
}

Exemplo de animação de árvore 4-5


Machine Translated by Google

Árvore

Folhas e flores As folhas são

criadas nos ramos superiores. Como as folhas são criadas ao mesmo tempo que os galhos da árvore, as
folhas são dimensionadas para 0 por leaf.setScaleX(0) e leaf.setScaleY(0) para ocultá-las antes que a árvore
cresça, conforme mostrado no Exemplo 4– 5. O mesmo truque é usado para esconder as folhas quando elas
caem. Para criar uma aparência mais natural, as folhas têm tons de verde ligeiramente diferentes. Além disso,
a cor da folha muda dependendo da localização da folha; os tons mais escuros são aplicados nas folhas
localizadas abaixo do meio da copa das árvores.

Exemplo 4–5 Formato e posicionamento da folha


public class Folha estende Elipse {

cor final pública AUTUMN_COLOR; int final


privado N = 5; private List<Elipse> pétalas =
new ArrayList<>(2 * N + 1);

public Leaf(Branch parentBranch) {


super(0, parentBranch.length / 2., 2, parentBranch.length / 2.); setScaleX(0); setScaleY(0);

rand duplo = random() * 0,5 + 0,3; AUTUMN_COLOR


= Color.color(random() * 0.1 + 0.8, rand, rand / 2);

Color color = new Color(random() * 0.5, random() * 0.5 + 0.5, 0, 1); if (parentBranch.globalH < 400
&& random() < 0.8) { //folha inferior é
mais escura

cor = cor.mais escuro();

} setFill(cor);
}
}
As flores são criadas na classe Flower e depois adicionadas aos galhos superiores da árvore na classe
TreeGenerator. Você pode especificar o número de pétalas em uma flor. As pétalas são elipses distribuídas
em círculo com algumas sobreposições. Semelhante à grama e às folhas, as pétalas das flores são coloridas
em diferentes tons de rosa.

Animando elementos da árvore


Esta seção explica as técnicas empregadas no exemplo de animação de árvore para animar a árvore e a
mudança de estação. A transição paralela é usada para iniciar todas as animações na cena, conforme
mostrado no Exemplo 4–6.

Exemplo 4–6 Animação principal


final Transition all = new ParallelTransition(new GrassWindAnimation(grama), treeWindAnimation, new
SequentialTransition(branchGrowingAnimation, seasonsAnimation(árvore, grama))); all.play();

Crescimento de
uma árvore A animação de crescimento de uma árvore é executada apenas uma vez, no início do
exemplo de animação de árvore. O aplicativo inicia uma animação de transição sequencial para aumentar as
ramificações uma geração após a outra, conforme mostrado no Exemplo 4–7. Inicialmente, o comprimento é
definido como 0. O tamanho e o ângulo do ramo raiz são especificados na classe TreeGenerator . Atualmente
cada geração é cultivada durante dois segundos.

4-6 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google

Árvore

Exemplo 4–7 Transição sequencial para iniciar a animação de crescimento de ramificação

SequentialTransition branchGrowingAnimation = new SequentialTransition();


O código no Exemplo 4–8 cria a animação Árvore crescendo:

Exemplo 4–8 Animação de crescimento de galhos

Animação privada animateBranchGrowing(List<Branch> branchGeneration) {

ParallelTransition sameDepthBranchAnimation = new ParallelTransition(); for (final Branch branch :


branchGeneration) {
Timeline branchGrowingAnimation = new Timeline(new KeyFrame(duração, new
KeyValue(branch.base.endYProperty(), branch.length)));
PauseTransition pausaTransition = new PauseTransition();
pauseTransition.setOnFinished(t -> branch.base.setStrokeWidth(branch.length /
25)); sameDepthBranchAnimation.getChildren().add(

new SequentialTransition(pauseTransition,
branchGrowingAnimation));

}
return sameDepthBranchAnimation;

}
Como todas as ramificações são calculadas e criadas simultaneamente, elas podem aparecer na cena
como pontos. O código apresenta alguns truques para ocultar as linhas antes que elas cresçam. No
exemplo, o código duration.one milisecond pausa a transição por um tempo imperceptível. No Exemplo 4–
9, o código base.setStrokeWidth(0) define a largura das ramificações como 0 antes do início da animação
de crescimento para cada geração.

Exemplo 4–9 Otimização de animação de crescimento de árvore

private void setBranchStyle(int depth) {


base.setStroke(Color.color(0.4, 0.1, 0.1, 1));

if (profundidade < 5)
{ base.setStrokeLineJoin(StrokeLineJoin.ROUND);
base.setStrokeLineCap(StrokeLineCap.ROUND);
}
base.setStrokeWidth(0);
}
}

Criando o movimento da copa da


árvore Paralelamente ao crescimento de uma árvore, a animação do vento começa. Galhos de
árvores, folhas e flores estão se movendo juntos.

A animação do vento da árvore é semelhante à animação do movimento da grama, mas é mais simples
porque apenas o ângulo dos galhos muda. Para fazer com que o movimento da árvore pareça natural, o
ângulo de dobra é diferente para diferentes gerações de galhos. Quanto maior a geração do galho (ou seja,
quanto menor o galho), mais ele se curva. O exemplo 4–10 fornece código para animação de vento.

Exemplo 4–10 Animação de Vento

private Animation animateTreeWind(List<Branch> branchGeneration, int depth) {


ParallelTransition vento = new ParallelTransition(); for (final Branch brunch :
branchGeneration) { rotação rotativa final = new Rotate(0);
brunch.getTransforms().add(rotação);

Exemplo de animação de árvore 4-7


Machine Translated by Google

Árvore

Timeline windTimeline = new Timeline(new KeyFrame(WIND_CYCLE_DURATION, new


KeyValue(rotation.angleProperty(), depth * 2)));
windTimeline.setAutoReverse(true);
windTimeline.setCycleCount(Animation.INDEFINITE);
wind.getChildren().add(windTimeline);
}
vento de retorno;
}

Animando a mudança de estação


A animação de mudança de estação realmente começa depois que a árvore cresce e é executada infinitamente.
O código no Exemplo 4–11 chama todas as animações da temporada:

Exemplo 4–11 Animação inicial da temporada


private Transition seasonsAnimation(final Tree tree, final List<Blade> grama) {

Transition spring = animateSpring(árvore.folha, grama); Flores de transição =


animateFlowers(tree.flowers); Outono de transição = animateAutumn(árvore.folha,
grama);

SequentialTransition sequencialTransition = novo


SequentialTransition(primavera, flores, outono);
return sequencialTransition;
}

private Transition animateSpring(List<Leaf> folhagem, List<Blade> grama) {


ParallelTransition springAnimation = new ParallelTransition(); for (lâmina final da lâmina:
grama) { springAnimation.getChildren().add(new
FillTransition(GRASS_BECOME_GREEN_DURATION, lâmina,

(Cor) blade.getFill(), blade.SPRING_COLOR)); } for (Folha folha :


folhagem) {

ScaleTransition leafageAppear = new ScaleTransition(LEAF_APPEARING_ DURATION, folha);


leafageAppear.setToX(1); leafageAppear.setToY(1); springAnimation.getChildren().add(leafageAppear);

} return springAnimation;
}
Depois que todos os galhos da árvore estiverem crescidos, as folhas começarão a aparecer conforme
indicado no Exemplo 4–12.

Exemplo 4–12 Transição paralela para iniciar a animação de primavera e mostrar folhas
private Transition animateSpring(List<Leaf> folhagem, List<Blade> grama) {
ParallelTransition springAnimation = new ParallelTransition(); for (lâmina final da lâmina:
grama) {
springAnimation.getChildren().add(new FillTransition(GRASS_BECOME_GREEN_ DURATION, lâmina,

(Cor) blade.getFill(), blade.SPRING_COLOR));

} for (Leaf leaf : leafage) { ScaleTransition


leafageAppear = new ScaleTransition(LEAF_APPEARING_ DURATION, leaf);
leafageAppear.setToX(1);

4-8 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google

Árvore

leafageAppear.setToY(1);
springAnimation.getChildren().add(leafageAppear); }

return springAnimation; }

Quando todas as folhas estiverem visíveis, as flores começam a aparecer conforme mostrado no
Exemplo 4–13. A transição sequencial é usada para mostrar as flores gradualmente. O atraso no
aparecimento da flor é definido no código de transição sequencial do Exemplo 4–13. As flores aparecem
apenas na copa das árvores.

Exemplo 4–13 Mostrando Flores

Transição privada animateFlowers(List<Flower> flowers) {

ParallelTransition flowersAppearAndFallDown = new ParallelTransition();

for (int i = 0; i < flores.tamanho(); i++) { final Flor flor =


flores.get(i); for (Elipse pental: flor.getPetals()) {

FadeTransition flowerAppear = new FadeTransition(FLOWER_APPEARING_ DURATION,


pétala); florAppear.setToValue(1); flowerAppear.setDelay(FLOWER_APPEARING_ DURATION.divide(3).multiply(i + 1));

floresAppearAndFallDown.getChildren().add(novo
SequentialTransition(new SequentialTransition(flowerAppear,
fakeFallDownAnimation(pétala))));

}
}
return floresAppearAndFallDown;
}
Assim que todas as flores aparecem na tela, suas pétalas começam a cair. No código do Exemplo
4–14, as flores são duplicadas e o primeiro conjunto delas é ocultado para ser mostrado posteriormente.

Exemplo 4–14 Duplicando pétalas

private Ellipse copyEllipse(Elipse petalOld, Color color) {


Elipse elipse = new Ellipse();
ellipse.setRadiusX(petalOld.getRadiusX());
ellipse.setRadiusY(petalOld.getRadiusY()); if (cor == null) {

ellipse.setFill(petalOld.getFill()); } outro {

elipse.setFill(cor);
}
ellipse.setRotate(petalOld.getRotate()); elipse.setOpacity(0);
elipse de retorno;

}
As pétalas de flores copiadas começam a cair no chão uma a uma, conforme mostrado no Exemplo 4–15.
As pétalas desaparecem após cinco segundos no chão. A trajetória de queda de uma pétala não é uma
linha reta, mas sim uma curva senoidal calculada, de modo que as pétalas parecem estar girando enquanto
caem.

Exemplo 4–15 Derramando Flores

Animação fakeLeafageDown = fakeFallDownEllipseAnimation(folha, folha.AUTUMN_COLOR,

Exemplo de animação de árvore 4-9


Machine Translated by Google

Arquivos de aplicativos

nó -> {
node.setScaleX(0);
node.setScaleY(0);
});
A próxima mudança de estação começa quando todas as flores desaparecem de cena. As folhas
e a grama ficam amarelas, e as folhas caem e desaparecem. O mesmo algoritmo usado no Exemplo 4–
15 para fazer as pétalas das flores caírem é usado para mostrar as folhas que caem. O código no
Exemplo 4–16 habilita a animação de outono.

Exemplo 4–16 Animando mudanças de outono


Transição privada animateAutumn(List<Folha> folhagem, List<Lâmina> grama) {
Outono de ParallelTransition = new ParallelTransition();

ParallelTransition folha amarela = new ParallelTransition();


ParallelTransition dissappearLeafage = new ParallelTransition();

for (folha final folha : folhagem) {

final FillTransition toYellow =


new FillTransition(LEAF_BECOME_YELLOW_DURATION, folha, nulo, folha.AUTUMN_COLOR);

Animação fakeLeafageDown = fakeFallDownEllipseAnimation(folha, folha.AUTUMN_COLOR,nó


-> {
node.setScaleX(0);
node.setScaleY(0);
});
dissappearLeafage.getChildren().add(fakeLeafageDown); }

ParallelTransition grassBecomeYellowAnimation = new ParallelTransition(); for (lâmina final da lâmina:


grama) {
final FillTransition toYellow =novo
FillTransition(GRASS_BECOME_YELLOW_DURATION, lâmina, (Cor) lâmina.getFill(), lâmina.AUTUMN_COLOR);

toYellow.setDelay(Duração.segundos(1 * random()));
gramaBecomeYellowAnimation.getChildren().add(toYellow); }

outono.getChildren().addAll(grassBecomeYellowAnimation, novo
SequentialTransition(yellowLeafage, dissappearLeafage)); retorno outono;

}
Depois que todas as folhas desaparecem do chão, a animação da primavera começa colorindo a
grama de verde e mostrando as folhas.

Arquivos de aplicativos
Projetos NetBeans

ÿ tree_animation.zip

4-10 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google

Parte III
Parte IIICriando efeitos visuais

Este tutorial contém os seguintes tópicos:


ÿ Efeito de mistura

ÿ Efeito Bloom

ÿ Efeitos de desfoque

ÿ Efeito de sombra projetada


ÿ Efeito de sombra interna

ÿ Reflexão

ÿ Efeito de iluminação

ÿ Efeito de perspectiva ÿ

Criação de uma cadeia de efeitos


Machine Translated by Google
Machine Translated by Google

5
5Aplicando efeitos

Este tutorial descreve como usar efeitos visuais para aprimorar a aparência de seu aplicativo
JavaFX.

Todos os efeitos estão localizados no pacote javafx.scene.effect e são subclasses da classe Effect .
Para obter mais informações sobre classes, métodos ou recursos adicionais específicos, consulte a
documentação da API.

Efeito de Mistura
Blend é um efeito que combina duas entradas usando um dos modos de mesclagem predefinidos.

No caso de uma combinação de nó (node.setBlendMode()), as duas entradas são: ÿ O

nó sendo renderizado (uma entrada superior) ÿ Tudo abaixo do nó (uma entrada inferior)

A determinação da entrada inferior é baseada nas seguintes regras: ÿ Todos os

irmãos de ordem Z inferior no mesmo grupo são incluídos.

ÿ Se o grupo tiver um modo de mesclagem definido, o processo será interrompido e a entrada


inferior será definida.

ÿ Se o grupo tiver o modo de mesclagem padrão, tudo abaixo do grupo será incluído, recursivamente
usando essa mesma regra.

ÿ Se o processo retornar recursivamente ao nó raiz, a pintura de fundo da cena será incluída.

Nota: Se a pintura de fundo da cena, que geralmente é uma cor opaca,


estiver incluída na entrada inferior, o modo SRC_ATOP renderiza em uma fonte
inferior completamente opaca e não tem efeito. Neste caso, o modo SRC_ATOP é
equivalente a SRC_OVER.

Um modo de mesclagem define a maneira pela qual os objetos são misturados. Por exemplo, na
Figura 5–1, você pode ver exemplos de alguns modos de mesclagem aplicados a um círculo
agrupado com um quadrado.

Aplicando efeitos 5-1


Machine Translated by Google

Efeito Bloom

Figura 5–1 Diferentes modos de mesclagem

O exemplo 5–1 mostra um trecho de código para o efeito de mesclagem no aplicativo de amostra.

Exemplo 5–1 Efeito de mesclagem


nó estático blendMode() {
Retângulo r = new Retângulo(); r.setX(590);

r.setY(50);
r.setWidth(50);
r.setHeight(50);
r.setFill(Color.BLUE);

Círculo c = new Círculo();


c.setFill(Color.RED);
c.setCenterX(590);
c.setCenterY(50);
c.setRadius(25);
c.setBlendMode(BlendMode.SRC_ATOP);

Grupo g = new Grupo();


g.setBlendMode(BlendMode.SRC_OVER);
g.getChildren().add(r); g.getChildren().add(c);
retornar g;

Efeito Bloom
O efeito bloom faz com que as partes mais brilhantes de uma imagem pareçam brilhar, com
base em um limite configurável. O limite varia de 0,0 a 1,0. Por padrão, o limite é definido como 0,3.

A Figura 5–2 mostra o efeito bloom no limite padrão e em um limite de 1,0.

5-2 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google
efeitos de desfoque

Figura 5–2 Efeito Bloom

O exemplo 5–2 mostra um trecho de código do aplicativo de exemplo que está usando o efeito bloom.

Exemplo 5–2 Exemplo de Bloom


nó estático bloom() {
Grupo g = new Grupo();

Retângulo r = new Retângulo(); r.setX(10);


r.setY(10); r.setWidth(160); r.setHeight(80);
r.setFill(Color.DARKBLUE);

Texto t = new Texto();


t.setText("Bloom!");
t.setFill(Color.YELLOW);
t.setFont(Font.font("null", FontWeight.BOLD, 36)); t.setX(25); t.setY(65);

g.setCache(verdadeiro); //
g.setEffect(new Bloom()); Bloom bloom
= new Bloom(); bloom.setThreshold(1.0);
g.setEffect(bloom); g.getChildren().add(r);
g.getChildren().add(t);
g.setTranslateX(350);

retornar g;
}

efeitos de desfoque
Desfoque são efeitos comuns que podem ser usados para fornecer mais foco aos objetos selecionados.
Com o JavaFX, você pode aplicar boxblur, motion blur ou gaussian blur.

Borrão de caixa

O BoxBlur é um efeito de desfoque que usa um kernel de filtro de caixa simples, com tamanhos
configuráveis separadamente em ambas as dimensões que controlam a quantidade de desfoque
aplicado a um objeto e um parâmetro de iterações que controla a qualidade do desfoque resultante.

A Figura 5–3 mostra duas amostras de texto borrado.

Aplicando efeitos 5-3


Machine Translated by Google
efeitos de desfoque

Figura 5–3 Efeito BoxBlur

O exemplo 5–3 é um trecho de código que usa o efeito BoxBlur.

Exemplo 5–3 Exemplo de BoxBlur

nó estático boxBlur() {
Texto t = new Texto();
t.setText("Texto embaçado!");
t.setFill(Color.RED);
t.setFont(Font.font("null", FontWeight.BOLD, 36)); t.setX(10); t.setY(40);

BoxBlur bb = new BoxBlur();


bb.setWidth(5); bb.setHeight(5);
bb.setIterations(3);

t.setEffect(bb);
t.setTranslateX(300);
t.setTranslateY(100);

retornar t;
}

Desfoque de movimento

Um efeito de desfoque de movimento usa um desfoque gaussiano, com raio e ângulo configuráveis para
criar o efeito de um objeto em movimento.

A Figura 5–4 mostra o efeito do desfoque de movimento em um texto.

Figura 5–4 Efeito de desfoque de movimento

O exemplo 5–4 mostra um trecho de código que cria um efeito de desfoque de movimento com raio definido
como 15 e ângulo definido como 45 no aplicativo de amostra.

Exemplo 5–4 Exemplo de desfoque de movimento

Nó static motionBlur() { Text t = new


Text(); t.setX(20.0f); t.setY(80.0f);
t.setText("Motion Blur");
t.setFill(Color.RED);
t.setFont(Font.font("null",
FontWeight.BOLD, 60));

5-4 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google

Efeito Sombra

MotionBlur mb = new MotionBlur();


mb.setRadius(15.0f);
mb.setAngle(45.0f);

t.setEffect(mb);

t.setTranslateX(300);
t.setTranslateY(150);

retornar t;
}

Desfoque gaussiano

O desfoque gaussiano é um efeito que usa um algoritmo gaussiano com um raio configurável para
desfocar objetos.

A Figura 5–5 mostra o efeito do desfoque gaussiano em um texto.

Figura 5–5 Desfoque Gaussiano

O exemplo 5–5 mostra um trecho de código que desfoca o texto usando o efeito de desfoque gaussiano.

Exemplo 5–5 Desfoque gaussiano


Static Node gaussianBlur() { Text t2 =
new Text(); t2.setX(10.0f);
t2.setY(140.0f);
t2.setCache(verdadeiro);
t2.setText("Gaussian Blur");
t2.setFill(Color.RED);
t2.setFont(Font.font("null",
FontWeight.BOLD, 36)); t2.setEffect(new GaussianBlur()); retornar t2;

Efeito Sombra Uma sombra projetada é um efeito que renderiza uma sombra do conteúdo ao qual é aplicada.
Você pode especificar a cor, o raio, o deslocamento e alguns outros parâmetros da sombra.

A Figura 5–6 mostra o efeito de sombra em diferentes objetos.

Figura 5–6 Exemplo de sombra projetada

Aplicando efeitos 5-5


Machine Translated by Google

Efeito Sombra

O exemplo 5–6 mostra como criar uma sombra no texto e um círculo.

Exemplo 5–6 Texto e círculo com sombras


importar javafx.collections.ObservableList; importar
javafx.application.Application; importar javafx.scene.*; importar
javafx.stage.*; importar javafx.scene.shape.*; importar
javafx.scene.effect.*; importar javafx.scene.paint.*; importar
javafx.scene.text.*;

public class HelloEffects extends Application {

Palco de palco;
Cena da cena;

@Sobrepor
public void start(Stage stage) { stage.show();

cena = nova Cena(novo Grupo(), 840, 680); ObservableList<Node>


content = ((Group)scene.getRoot()).getChildren();

content.add(dropShadow());
palco.setScene(cena);
}

Nó estático dropShadow() {
Grupo g = new Grupo();

DropShadow ds = new DropShadow();


ds.setOffsetY(3.0);
ds.setOffsetX(3.0);
ds.setColor(Color.GRAY);

Texto t = new Texto();


t.setEffect(ds);
t.setCache(verdadeiro);
t.setX(20.0f);
t.setY(70.0f);
t.setFill(Color.RED);
t.setText("Efeito de sombreamento JavaFX");
t.setFont(Font.font("null", FontWeight.BOLD, 32));

DropShadow ds1 = new DropShadow();


ds1.setOffsetY(4.0f); ds1.setOffsetX(4.0f);

ds1.setColor(Cor.CORAL);

Círculo c = new Círculo();


c.setEffect(ds1);
c.setCenterX(50.0f);
c.setCenterY(325.0f);
c.setRadius(30.0f);
c.setFill(Color.RED);
c.setCache(verdadeiro);

g.getChildren().add(t);

5-6 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google

Efeito de sombra interna

g.getChildren().add(c); retornar g;

}
public static void main(String[] args) { Application.launch(args);

}
}

Dica:

ÿ Tornar o sombreamento muito amplo dá ao elemento uma


aparência de peso. A cor da sombra deve ser realista,
geralmente alguns tons mais claros que a cor de fundo.
ÿ Se você tiver vários objetos com sombreamentos, oriente o
sombreamento da mesma forma para todos os objetos. Uma sombra
projetada dá a aparência de uma luz vindo de uma direção e lançando
uma sombra sobre os objetos.

Efeito de sombra interna


Uma sombra interna é um efeito que renderiza uma sombra dentro das bordas do conteúdo
fornecido com a cor, raio e deslocamento especificados.

A Figura 5–7 mostra texto simples e o mesmo texto com o efeito de sombra interna aplicado.

Figura 5–7 Sombra interna

O exemplo 5–7 mostra como criar uma sombra interna no texto.

Exemplo 5–7 Sombra interna


static Node innerShadow()
{ InnerShadow is = new InnerShadow();
is.setOffsetX(2.0f); is.setOffsetY(2.0f);

Texto t = new Texto();


t.setEffect(é);
t.setX(20);
t.setY(100);
t.setText("Sombra Interna");
t.setFill(Color.RED);
t.setFont(Fonte.font("null", FontWeight.BOLD, 80));

t.setTranslateX(300);
t.setTranslateY(300);

Aplicando efeitos 5-7


Machine Translated by Google
Reflexão

retornar t;
}

Reflexão
A reflexão é um efeito que renderiza uma versão refletida do objeto abaixo do objeto real.

Nota: A reflexão de um nó com um efeito de reflexão não


responderá aos eventos do mouse ou aos métodos de contenção no nó.

A Figura 5–8 mostra um reflexo aplicado ao texto. Use o método setFraction para especificar
a quantidade de reflexão visível.

Figura 5–8 Efeito de reflexão

O exemplo 5–8 mostra como criar o efeito de reflexão no texto.

Exemplo 5–8 Texto com reflexão


importar javafx.scene.text.*; importar
javafx.scene.paint.*; importar
javafx.scene.effect.*; public class
HelloEffects extends Application {

Palco de palco;
Cena da cena;

@Override public void start(Stage stage) { stage.show();

cena = nova Cena(novo Grupo(), 840, 680);


ObservableList<Node> content = ((Group)scene.getRoot()).getChildren(); content.add(reflection());
palco.setScene(cena);

} static Node reflection() { Text t = new


Text(); t.setX(10.0f); t.setY(50.0f);
t.setCache(verdadeiro);
t.setText("Reflexão em
JavaFX..."); t.setFill(Color.RED);
t.setFont(Fonte.font("null", FontWeight.BOLD, 30));

Reflexão r = new Reflexão(); r.setFraction(0.9);

t.setEffect(r);

t.setTranslateY(400);
retornar t;

5-8 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google

Efeito de iluminação

}
public static void main(String[] args) { Application.launch(args);

}
}

Efeito de iluminação
O efeito de iluminação simula uma fonte de luz brilhando no conteúdo fornecido, que pode ser usado
para dar a objetos planos uma aparência tridimensional mais realista.

A Figura 5–9 mostra o efeito de iluminação no texto.

Figura 5–9 Efeito de iluminação

O exemplo 5–9 mostra como criar um efeito de iluminação no texto.

Exemplo 5–9 Texto com efeito de iluminação aplicado


importar javafx.application.Application; importar
javafx.collections.ObservableList; importar
javafx.geometry.VPos; importar javafx.scene.effect.Light.Distant;
importar javafx.scene.*; importar javafx.stage.*; importar
javafx.scene.shape.*; importar javafx.scene.effect.*; importar
javafx.scene.paint.*; importar javafx.scene.text.*;

public class HelloEffects extends Application {


Palco de palco;
Cena da cena;

@Override public void start(Stage stage) { stage.show();

cena = nova Cena(novo Grupo());


ObservableList<Node> content = ((Group)scene.getRoot()).getChildren();

content.add(iluminação());
palco.setScene(cena);

} static Node lighting() { Luz distante


= new Distant(); light.setAzimuth(-135.0f);

Iluminação l = new Iluminação();


l.setLight(luz); l.setSurfaceScale(5.0f);

Aplicando efeitos 5-9


Machine Translated by Google

Efeito de perspectiva

Texto t = new Texto();


t.setText("JavaFX"+"\n"+"Iluminação!");
t.setFill(Color.RED);
t.setFont(Fonte.font("null", FontWeight.BOLD, 70)); t.setX(10.0f);

t.setY(10.0f);
t.setTextOrigin(VPos.TOP);

t.setEffect(l);

t.setTranslateX(0);
t.setTranslateY(320);

retornar t;
}
public static void main(String[] args) { Application.launch(args);

}
}

Efeito de perspectiva
O efeito de perspectiva cria um efeito tridimensional de um objeto bidimensional.

A Figura 5–10 mostra o efeito de perspectiva.

Figura 5–10 Efeito de perspectiva

Uma transformação de perspectiva pode mapear qualquer quadrado para outro quadrado,
preservando a retidão das linhas. Ao contrário das transformações afins, o paralelismo das
linhas na origem não é necessariamente preservado na saída.

Nota: Este efeito não ajusta as coordenadas dos eventos de entrada ou quaisquer métodos que
medem a contenção em um nó. O clique do mouse e os métodos de contenção são indefinidos
se um efeito de perspectiva for aplicado a um nó.

O exemplo 5–10 é um trecho de código do aplicativo de amostra que mostra como criar um
efeito de perspectiva.

Exemplo 5–10 Efeito de perspectiva


static Node perspective() { Group g =
new Group(); PerspectiveTransform
pt = new PerspectiveTransform(); pt.setUlx(10.0f); pt.setUly(10.0f);
pt.setUrx(210.0f); pt.setUry(40.0f);

5-10 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google

Criando uma Cadeia de Efeitos

pt.setLrx(210.0f);
pt.setLry(60.0f);
pt.setLlx(10.0f);
pt.setLly(90.0f);

g.setEffect(pt);
g.setCache(verdadeiro);

Retângulo r = new Retângulo(); r.setX(10.0f);

r.setY(10.0f);
r.setWidth(280.0f);
r.setHeight(80.0f);
r.setFill(Color.DARKBLUE);

Texto t = new Texto();


t.setX(20.0f);
t.setY(65.0f);
t.setText("Perspectiva");
t.setFill(Color.RED);
t.setFont(Font.font("null", FontWeight.BOLD, 36));

g.getChildren().add(r);
g.getChildren().add(t); retornar g;

A Figura 5–11 mostra quais coordenadas afetam a imagem resultante.

Figura 5–11 Coordenadas para efeito de perspectiva

Criando uma Cadeia de Efeitos


Alguns dos efeitos possuem uma propriedade de entrada que você pode usar para criar uma cadeia de efeitos.
A cadeia de efeitos pode ser uma estrutura semelhante a uma árvore, porque alguns efeitos têm duas
entradas e outros não.

Na Figura 5–12, o efeito de reflexo é usado como uma entrada para o efeito de sombreamento, o que
significa que primeiro o retângulo é refletido pelo efeito de reflexo e, em seguida, o efeito de sombreamento
é aplicado ao resultado.

Aplicando efeitos 5-11


Machine Translated by Google

Criando uma Cadeia de Efeitos

Figura 5–12 Sombra e Reflexão

Exemplo 5–11 Retângulo com sombra e reflexo aplicados sequencialmente


importar javafx.application.Application; importar
javafx.collections.ObservableList; importar javafx.scene.*;
importar javafx.stage.*; importar javafx.scene.shape.*;
importar javafx.scene.effect.*; importar javafx.scene.paint.*;
importar javafx.scene.text.*;

public class HelloEffects extends Application {

Palco de palco;
Cena da cena;

@Override public void start(Stage stage) { stage.show();

cena = nova Cena(novo Grupo());


ObservableList<Node> content = ((Group)scene.getRoot()).getChildren();

content.add(chainEffects());
palco.setScene(cena);

} static Node chainEffects() {

Retângulo retângulo = new Retângulo();


rect.setFill(Color.RED); rect.setWidth(200);
rect.setHeight(100); rect.setX(20.0f);

rect.setY(20.0f);

DropShadow ds = new DropShadow();


ds.setOffsetY(5.0);
ds.setOffsetX(5.0);
ds.setColor(Color.GRAY);

Reflexão reflexão = new Reflexão();

ds.setInput(reflexão);
rect.setEffect(ds);

retornar reto;
}

5-12 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google

Arquivos de aplicativos

public static void main(String[] args) { Application.launch(args);

}
}

Nota: Se você alterar as duas últimas linhas no método chainEffects() para


reflection.setInput(ds); e rect.setEffect(reflection);, primeiro a sombra projetada
será aplicada ao retângulo e, em seguida, o resultado será refletido pelo efeito
de reflexão.

Para obter mais informações sobre classes, métodos ou recursos adicionais específicos, consulte
a documentação da API.

Arquivos de aplicativos
Projetos NetBeans

ÿ visual_effects.zip

Aplicando efeitos 5-13


Machine Translated by Google

Arquivos de aplicativos

5-14 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google

Parte IV
Parte IV Código Fonte para as Transformações,
Tutorial de Animações e Efeitos Visuais

A tabela a seguir lista os aplicativos de demonstração neste documento com seus arquivos de
código-fonte associados.

Projeto NetBeans
Tutorial Código fonte Arquivo

Transformações Xilofone.java transformações.zip


Visão geral

Noções básicas de animação animações.zip

Animação da Árvore tree_animation.zip


Exemplo

Criando Visuais visual_effects.zip


efeitos
Machine Translated by Google
Machine Translated by Google

A
AXylophone.java

Para obter uma descrição, consulte Tipos e exemplos de transformação.

Termos legais e aviso de direitos autorais


/*
* Copyright (c) 2010, 2014, Oracle e/ou suas afiliadas.
* Todos os direitos reservados. O uso está sujeito aos termos de licença.
*

* Este arquivo está disponível e licenciado sob a seguinte licença:


*

* A redistribuição e uso em fontes e formas binárias, com ou sem * modificação, são permitidos
desde que as seguintes condições
* são atendidas:
*
*
- As redistribuições do código-fonte devem manter o aviso de direitos autorais acima, esta
*
lista de condições e a seguinte isenção de responsabilidade.
*
- As redistribuições em formato binário devem reproduzir o aviso de direitos autorais acima,
*
esta lista de condições e a seguinte isenção de responsabilidade na documentação e/ou
*
outros materiais fornecidos com a distribuição.
* - Nem o nome do Oráculo nem os nomes de seus
*
colaboradores podem ser usados para endossar ou promover produtos derivados deste
*
software sem permissão prévia específica por escrito.
*
* ESTE SOFTWARE É FORNECIDO PELOS DETENTORES DOS DIREITOS AUTORAIS E COLABORADORES
* "COMO ESTÁ" E QUAISQUER GARANTIAS EXPRESSAS OU IMPLÍCITAS, INCLUINDO, MAS NÃO
* LIMITADO ÀS GARANTIAS IMPLÍCITAS DE COMERCIABILIDADE E ADEQUAÇÃO PARA
* UM PROPÓSITO ESPECÍFICO SÃO REJEITADOS. EM NENHUM CASO OS DIREITOS AUTORAIS
* O PROPRIETÁRIO OU OS COLABORADORES SERÃO RESPONSÁVEIS POR QUALQUER COISA DIRETA, INDIRETA, INCIDENTAL,
* DANOS ESPECIAIS, EXEMPLARES OU CONSEQUENTES (INCLUINDO, MAS NÃO
* LIMITADO À AQUISIÇÃO DE BENS OU SERVIÇOS SUBSTITUTOS; PERDA DE USO,
* DADOS OU LUCROS; OU INTERRUPÇÃO DE NEGÓCIOS) DE QUALQUER CAUSA E DE QUALQUER
* TEORIA DA RESPONSABILIDADE, SEJA EM CONTRATO, RESPONSABILIDADE ESTRITA OU ILÍCITO
* (INCLUINDO NEGLIGÊNCIA OU OUTROS) DECORRENTES DE QUALQUER FORMA DO USO
* DESTE SOFTWARE, MESMO SE AVISADO DA POSSIBILIDADE DE TAIS DANOS. */

Código
pacote xilofone;

importar javafx.application.Application; importar


javafx.event.EventHandler; importar
javafx.geometry.Bounds; importar
javafx.scene.DepthTest; importar javafx.scene.Group;
importar javafx.scene.PerspectiveCamera;

Xilofone.java A-1
Machine Translated by Google

importar javafx.scene.Scene; importar


javafx.scene.input.KeyCode; importar
javafx.scene.input.KeyEvent; importar
javafx.scene.input.MouseEvent; importar
javafx.scene.media.AudioClip; importar
javafx.scene.paint.Color; importar
javafx.scene.paint.CycleMethod; importar
javafx.scene.paint.RadialGradient; importar
javafx.scene.paint.Stop; import javafx.scene.shape.Rectangle;
importar javafx.scene.transform.Rotate; import
javafx.scene.transform.Scale; importar
javafx.scene.transform.Shear; importar
javafx.scene.transform.Translate; importar javafx.stage.Stage;

public class Xylophone estende o aplicativo {

mousePosX duplo;
mousePosY duplo;
duplo mouseOldX; duplo
mouseOldY; mouseDeltaX
duplo;
mouseDeltaY duplo;

final Cam camOffset = new Cam();


final Cam cam = new Cam();

final Shear shear = new Shear();

classe Cam estende Grupo {


Traduzir t = new Traduzir();
Traduzir p = new Traduzir();
Traduzir ip = new Traduzir();
Girar rx = new Girar();
{ rx.setAxis(Girar.X_AXIS); }
Girar ry = new Girar();
{ ry.setAxis(Girar.Y_AXIS); }
Girar rz = new Girar();
{ rz.setAxis(Girar.Z_AXIS); }
Escala s = new Escala();
public Cam() { super(); getTransforms().addAll(t, p, rx, rz, ry, s, ip); }
}

@Override public void start(fase final) {


stage.setTitle("Xilofone");

camOffset.getChildren().add(cam); resetCam();

cena final cena = nova cena(camOffset, 800, 600, true); cena.setFill(new


RadialGradient(225, 0.85, 300, 300, 500, false, CycleMethod.NO_CYCLE, new Stop[] { new
Stop(0f, Color.BLUE), new Stop(1f,
Color.LIGHTBLUE) })) ;

cena.setCamera(new PerspectiveCamera());

final AudioClip bar1Nota =


novo
AudioClip(Xylophone.class.getResource("audio/Note1.wav").toString());

A-2 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google

final AudioClip bar2Nota =


novo
AudioClip(Xylophone.class.getResource("audio/Note2.wav").toString()); final AudioClip bar3Nota =

novo
AudioClip(Xylophone.class.getResource("audio/Note3.wav").toString()); final AudioClip bar4Note =

novo
AudioClip(Xylophone.class.getResource("audio/Note4.wav").toString()); final AudioClip bar5Nota =

novo
AudioClip(Xylophone.class.getResource("audio/Note5.wav").toString()); final AudioClip bar6Nota =

novo
AudioClip(Xylophone.class.getResource("audio/Note6.wav").toString()); final AudioClip bar7Nota =

novo
AudioClip(Xylophone.class.getResource("audio/Note7.wav").toString()); final AudioClip bar8Nota =

novo
AudioClip(Xylophone.class.getResource("audio/Note8.wav").toString());

Grupo retânguloGrupo = new Grupo();


retânguloGroup.getTransforms().add(shear);
retânguloGroup.setDepthTest(DepthTest.ENABLE);

duplo xStart = 260,0; duplo


xOffset = 30,0; duplo yPos =
300,0; duplo zPos = 0,0; largura
da barra dupla = 22,0; double
barDepth = 7,0;

// Base1
Cubo base1Cube = new Cube(1.0, new Color(0.2, 0.12, 0.1, 1.0), 1.0);
base1Cube.setTranslateX(xStart + 135);
base1Cube.setTranslateZ(yPos+20.0);
base1Cube.setTranslateY(11.0);
base1Cube.setScaleX(barWidth*11.5);
base1Cube.setScaleZ(10.0);
base1Cube.setScaleY(barDepth*2.0);

// Base2
Cubo base2Cube = new Cube(1.0, new Color(0.2, 0.12, 0.1, 1.0), 1.0);
base2Cube.setTranslateX(xStart + 135);
base2Cube.setTranslateZ(yPos-20.0);
base2Cube.setTranslateY(11.0);
base2Cube.setScaleX(barWidth*11.5);
base2Cube.setScaleZ(10.0);
base2Cube.setScaleY(barDepth*2.0);

// Bar1
Cubo bar1Cube = new Cube(1.0, Color.PURPLE, 1.0);
bar1Cube.setTranslateX(xStart + 1*xOffset); bar1Cube.setTranslateZ(yPos);
bar1Cube.setScaleX(barWidth); bar1Cube.setScaleZ(100.0);
bar1Cube.setScaleY(barDepth);

// Bar2

Xilofone.java A-3
Machine Translated by Google

Cubo bar2Cube = new Cube(1.0, Color.BLUEVIOLET, 1.0);


bar2Cube.setTranslateX(xStart + 2*xOffset);
bar2Cube.setTranslateZ(yPos);
bar2Cube.setScaleX(barWidth);
bar2Cube.setScaleZ(95.0);
bar2Cube.setScaleY(barDepth);

// Compasso3

Cubo bar3Cube = new Cube(1.0, Color.BLUE, 1.0);


bar3Cube.setTranslateX(xStart + 3*xOffset);
bar3Cube.setTranslateZ(yPos);
bar3Cube.setScaleX(barWidth);
bar3Cube.setScaleZ(90.0);
bar3Cube.setScaleY(barDepth);

// Bar4
Cubo bar4Cube = new Cube(1.0, Color.GREEN, 1.0);
bar4Cube.setTranslateX(xStart + 4*xOffset);
bar4Cube.setTranslateZ(yPos); bar4Cube.setScaleX(barWidth);

bar4Cube.setScaleZ(85.0);
bar4Cube.setScaleY(barDepth);

// Compasso5

Cubo bar5Cube = new Cube(1.0, Color.GREENYELLOW, 1.0);


bar5Cube.setTranslateX(xStart + 5*xOffset);
bar5Cube.setTranslateZ(yPos);
bar5Cube.setScaleX(barWidth);
bar5Cube.setScaleZ(80.0);
bar5Cube.setScaleY(barDepth);

// Bar6
Cubo bar6Cube = new Cube(1.0, Color.YELLOW, 1.0);
bar6Cube.setTranslateX(xStart + 6*xOffset); bar6Cube.setTranslateZ(yPos);
bar6Cube.setScaleX(barWidth); bar6Cube.setScaleZ(75.0);
bar6Cube.setScaleY(barDepth);

// Compasso7

Cubo bar7Cube = new Cube(1.0, Color.ORANGE, 1.0);


bar7Cube.setTranslateX(xStart + 7*xOffset);
bar7Cube.setTranslateZ(yPos); bar7Cube.setScaleX(barWidth);

bar7Cube.setScaleZ(70.0);
bar7Cube.setScaleY(barDepth);

// Compasso8

Cubo bar8Cube = new Cube(1.0, Color.RED, 1.0);


bar8Cube.setTranslateX(xStart + 8*xOffset);
bar8Cube.setTranslateZ(yPos);
bar8Cube.setScaleX(barWidth);
bar8Cube.setScaleZ(65.0);
bar8Cube.setScaleY(barDepth);

bar1Cube.setOnMousePressed(new EventHandler<MouseEvent>() {
@Sobrepor
public void handle(MouseEvent me) { bar1Note.play(); }
});
bar2Cube.setOnMousePressed(new EventHandler<MouseEvent>() {

A-4 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google

@Sobrepor
public void handle(MouseEvent me) { bar2Note.play(); }
});
bar3Cube.setOnMousePressed(new EventHandler<MouseEvent>() {
@Sobrepor
public void handle(MouseEvent me) { bar3Note.play(); }
});
bar4Cube.setOnMousePressed(new EventHandler<MouseEvent>() {
@Sobrepor
public void handle(MouseEvent me) { bar4Note.play(); }
});
bar5Cube.setOnMousePressed(new EventHandler<MouseEvent>() {
@Sobrepor
public void handle(MouseEvent me) { bar5Note.play(); }
});
bar6Cube.setOnMousePressed(new EventHandler<MouseEvent>() {
@Sobrepor
public void handle(MouseEvent me) { bar6Note.play(); }
});
bar7Cube.setOnMousePressed(new EventHandler<MouseEvent>() {
@Sobrepor
public void handle(MouseEvent me) { bar7Note.play(); }
});
bar8Cube.setOnMousePressed(new EventHandler<MouseEvent>() {
@Sobrepor
public void handle(MouseEvent me) { bar8Note.play(); }
});

retânguloGroup.getChildren().addAll(base1Cube, base2Cube, bar1Cube, bar2Cube,


bar3Cube, bar4Cube, bar5Cube, bar6Cube,
bar7Cube, bar8Cube);

retânguloGroup.setScaleX(2.5);
retânguloGroup.setScaleY(2.5);
retânguloGroup.setScaleZ(2.5);
cam.getChildren().add(rectangleGroup);

frameCam(palco, cena);

cena.setOnMousePressed(new EventHandler<MouseEvent>() {
@Sobrepor
public void handle(MouseEvent me) { mousePosX =
me.getX(); mousePosY = me.getY(); mouseOldX
= me.getX(); mouseVelhoY = me.getY(); //
System.out.println("scene.setOnMousePressed"

+ eu);
}
});
cena.setOnMouseDragged(new EventHandler<MouseEvent>() {
@Sobrepor
public void handle(MouseEvent me) { mouseOldX =
mousePosX; mouseVelhoY = mousePosY;
mousePosX = me.getX(); mousePosY = me.getY();
mouseDeltaX = mousePosX - mouseOldX;
mouseDeltaY = mousePosY - mouseOldY; if
(me.isAltDown() && me.isShiftDown() &&
me.isPrimaryButtonDown()) {

Xilofone.java A-5
Machine Translated by Google

double rzAngle = cam.rz.getAngle();


cam.rz.setAngle(rzAngle - mouseDeltaX);
}
else if (me.isAltDown() && me.isPrimaryButtonDown()) {
double ryAngle = cam.ry.getAngle();
cam.ry.setAngle(ryAngle - mouseDeltaX); double rxAngle
= cam.rx.getAngle(); cam.rx.setAngle(rxAngle +
mouseDeltaY);
}
else if (me.isShiftDown() && me.isPrimaryButtonDown()) {
double yShear = shear.getY();
shear.setY(yShear + mouseDeltaY/1000.0); double xShear
= shear.getX(); shear.setX(xShear + mouseDeltaX/1000.0);

}
else if (me.isAltDown() && me.isSecondaryButtonDown()) {
escala dupla = cam.s.getX(); double
newScale = escala + mouseDeltaX*0.01; cam.s.setX(novaEscala);
cam.s.setY(novaEscala);

cam.s.setZ(novaEscala);
}
else if (me.isAltDown() && me.isMiddleButtonDown()) {
double tx = cam.t.getX(); double ty
= cam.t.getY(); cam.t.setX(tx +
mouseDeltaX);
cam.t.setY(ty + mouseDeltaY);
}
}
});
cena.setOnKeyPressed(new EventHandler<KeyEvent>() { @Override

public void handle(KeyEvent ke) {


if (KeyCode.A.equals(ke.getCode())) { resetCam();

shear.setX(0.0);
shear.setY(0.0);
}
if (KeyCode.F.equals(ke.getCode())) { frameCam(palco,
cena); shear.setX(0.0);

shear.setY(0.0);
}
if (KeyCode.SPACE.equals(ke.getCode())) { if
(stage.isFullScreen()) {
stage.setFullScreen(false);
frameCam(palco, cena); } outro {

stage.setFullScreen(true);
frameCam(palco, cena);
}
}
}
});

palco.setScene(cena);
palco.show();
}

//================================================ =========================

A-6 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google

// CubeSystem.frameCam //
============================================= ==============================
public void frameCam(fase final do palco, cena final da cena) {
setCamOffset(camOffset, cena);
// cam.resetTSP();
setCamPivot(cam);
setCamTranslate(cam);
setCamScale(câmera, cena);
}

//================================================ =========================
// CubeSystem.setCamOffset //
============================================= ==============================
public void setCamOffset(final Cam camOffset, cena final da cena) {
largura dupla = cena.getWidth(); altura dupla
= cena.getHeight(); camOffset.t.setX(largura/2.0);

camOffset.t.setY(altura/2.0);
}

//================================================ =========================
// definirCamScale
//================================================ =========================
public void setCamScale(final Cam cam, cena final da cena) { final Bounds bounds =
cam.getBoundsInLocal(); final duplo pivotX = limites.getMinX() + limites.getWidth()/
2; final duplo pivôY = limites.getMinY() + limites.getHeight()/2; final duplo pivotZ =
limites.getMinZ() + limites.getDepth()/2;

largura dupla = cena.getWidth(); altura dupla


= cena.getHeight();

double scaleFactor = 1.0; double


scaleFactorY = 1,0; double
scaleFactorX = 1,0;
if (bounds.getWidth() > 0,0001) { scaleFactorX
= largura /bounds.getWidth(); // / 2.0;
}
if (bounds.getHeight() > 0,0001) { scaleFactorY =
altura /bounds.getHeight(); // / 1.5;
}
if (scaleFactorX > scaleFactorY) {
Fatorescala = FatorescalaY; } outro {

Fatorescala = FatorescalaX;
}
cam.s.setX(scaleFactor);
cam.s.setY(scaleFactor);
cam.s.setZ(scaleFactor);
}

//================================================ =========================
// setCamPivot
//================================================ =========================
public void setCamPivot(final Cam cam) {
limites limites limites = cam.getBoundsInLocal(); final duplo pivotX
= limites.getMinX() + limites.getWidth()/2; final duplo pivôY = limites.getMinY() +
limites.getHeight()/2; final duplo pivotZ = limites.getMinZ() + limites.getDepth()/2;
cam.p.setX(pivotX);

Xilofone.java A-7
Machine Translated by Google

cam.p.setY(pivotY);
cam.p.setZ(pivotZ);
cam.ip.setX(-pivotX);
cam.ip.setY(-pivotY);
cam.ip.setZ(-pivotZ);
}

//================================================ =========================
// setCamTranslate
//================================================ =========================
public void setCamTranslate(câmera da câmera final) {
limites limites limites = cam.getBoundsInLocal(); final duplo pivotX
= limites.getMinX() + limites.getWidth()/2; final duplo pivôY = limites.getMinY() +
limites.getHeight()/2; cam.t.setX(-pivotX); cam.t.setY(-pivotY);

public void resetCam()


{ cam.t.setX(0.0);
cam.t.setY(0.0);
cam.t.setZ(0.0);
cam.rx.setAngle(45.0);
cam.ry.setAngle(-7.0);
cam.rz.setAngle(0.0);
cam.s.setX(1.25);
cam.s.setY(1.25);
cam.s.setZ(1.25);

cam.p.setX(0.0);
cam.p.setY(0.0);
cam.p.setZ(0.0);

cam.ip.setX(0.0);
cam.ip.setY(0.0);
cam.ip.setZ(0.0);

limites limites limites = cam.getBoundsInLocal(); final duplo pivotX


= limites.getMinX() + limites.getWidth() / 2; final duplo pivotY = limites.getMinY() +
limites.getHeight() / 2; final duplo pivotZ = limites.getMinZ() + limites.getDepth() / 2;

cam.p.setX(pivotX);
cam.p.setY(pivotY);
cam.p.setZ(pivotZ);

cam.ip.setX(-pivotX);
cam.ip.setY(-pivotY);
cam.ip.setZ(-pivotZ);
}

public class Cube extends Group { final Rotate


rx = new Rotate(0, Rotate.X_AXIS); final Rotate ry = new Rotate(0,
Rotate.Y_AXIS); final Rotate rz = new Rotate(0, Rotate.Z_AXIS);
public Cube(tamanho duplo, cor da cor, tom duplo)
{ getTransforms().addAll(rz, ry, rx);

// Face traseira

A-8 Transformações, animações e efeitos visuais do JavaFX


Machine Translated by Google

Rectangle backFace = new Rectangle(tamanho,tamanho);


backFace.setFill(color.deriveColor(0.0, 1.0, (1 - 0.5*sombra), 1.0));
backFace.setTranslateX(-0,5*tamanho);
backFace.setTranslateY(-0,5*tamanho);
backFace.setTranslateZ(-0,5*tamanho);

// face inferior
Rectangle bottomFace = new Rectangle(tamanho,tamanho);
bottomFace.setFill(color.deriveColor(0.0, 1.0, (1 - 0.4*sombra), 1.0)); bottomFace.setTranslateX(-0,5*tamanho);

bottomFace.setTranslateY(0);
bottomFace.setRotationAxis(Girar.X_AXIS);
bottomFace.setRotate(90);

// face direita
Retângulo face direita = new Rectangle(tamanho,tamanho);
rightFace.setFill(color.deriveColor(0.0, 1.0, (1 - 0.3*sombra), 1.0)); facedireita.setTranslateX(-1*tamanho);
facedireita.setTranslateY(-0,5*tamanho); facedireita.setRotationAxis(Girar.Y_AXIS);
facedireita.setRotate(90);

// faceesquerda

Rectangle leftFace = new Rectangle(tamanho,tamanho);


leftFace.setFill(color.deriveColor(0.0, 1.0, (1 - 0.2*sombra), 1.0)); leftFace.setTranslateX(0);

leftFace.setTranslateY(-0,5*tamanho);
leftFace.setRotationAxis(Rotate.Y_AXIS);
leftFace.setRotate(90);

// TopFace
Face superior do retângulo = new Rectangle(tamanho,tamanho);
topFace.setFill(color.deriveColor(0.0, 1.0, (1 - 0.1*sombra), 1.0)); topFace.setTranslateX(-0,5*tamanho);
topFace.setTranslateY(-1*tamanho); topFace.setRotationAxis(Girar.X_AXIS); topFace.setRotate(90);

// frontal
FrontFace do retângulo = new Rectangle(tamanho,tamanho);
frontFace.setFill(cor);
frontFace.setTranslateX(-0,5*tamanho);
frontFace.setTranslateY(-0,5*tamanho);
frontFace.setTranslateZ(-0,5*tamanho);

getChildren().addAll(backFace, bottomFace, rightFace, leftFace,


topFace,frontFace);

}
}

public static void main(String[] args) { Application.launch(args);

}
}

Xilofone.java A-9
Machine Translated by Google

A-10 Transformações, animações e efeitos visuais do JavaFX

Você também pode gostar