JavaFX 애니메이션 기능

JavaFX는 다양한 애니메이션 기능이 포함되어 있다. TransitionTimeline 같은 클래스를 사용하여 그래픽을 움직여 보자.

TranslateTransition 사용

JavaFX가 Swing 등에 비해 뛰어난 점 중 하나는 “애니메이션"이다. Swing에서 그래픽을 애니메이션하려고 하면 스레드와 타이머를 만들고 위치를 자주 이동하고 다시 그리고 등을 반복해야만 한다. 하지만 JavaFX라면 쉽게 애니메이션을 만들 수 있다.

애니메이션 관계의 기능은 javafx.animation 패키지에 여러가지 준비되어 있다. 우선 가장 많이 사용되는 “표시 위치를 이동"하는 것부터 사용해 보자.

이것은 “TranslateTransition"라는 클래스로 제공되고 있다. 이것은 애니메이션 관련 클래스의 가장 기본이다. 이 클래스의 사용법을 알면 다른 것도 대체로 동일하게 다를 수 있게 될 것이다.

이 TranslateTransition은 다음과 같은 형태로 인스턴스를 만듭니다.

new TranslateTransition();
new TranslateTransition("Duration");
new TranslateTransition("Duration", "Node");

인수는 아무것도 없는 것부터, Duration와 Node를 가진 것까지 여러가지를 갖추고 있다. 인수에 있는 “Node"는 움직이는 부품의 인스턴스이다. 그래픽라면 셰이프와 관련된 인스턴스를 여기에 지정한다.

또 다른 한개의 “Duration"은 javafx.util 패키지에 포함되어 있는 클래스로써, 애니메이션의 경과 시간을 처리하기위한 것이다. 이것은 다음과 같이 인스턴스를 만든다.

new Duration(밀리 );

이것으로 인수에 지정된 밀리 초 단위의 경과 시간을 나타내는 Duration 인스턴스를 사용할 수 있다. 이제 “어떤 모양을 일정 시간에 애니메이션으로 움직일까"라는 애니메이션의 기본 설정이 있다.

또한 인수로 Node와 Duration을 설정하지 않은 경우 나중에 메소드를 사용하여 이를 지정해야 한다.

"TranslateTransition".setNode ( "Node");
"TranslateTransition".setDuration ( "Duration");

이것들이 없으면 애니메이션 자체가 되지 않기 때문에, new 할 때 처음부터 인수로 지정해 두는 것이 좋다.

애니메이션 설정 메소드

TranslateTransition 인스턴스를 만들고 나서, 이어서 메소드를 호출하여 애니메이션에 대한 섬세한 설정을 실시하고 있다. 여기에는 다양한 방법이 준비되어 있지만, 우선 필요한 것은 다음과 같다.

이동하기 전의 위치를 설정하는 메소드

"TranslateTransition".setFromX("double");
"TranslateTransition".setFromY("double");
"TranslateTransition".setFromZ("double");

이동하는 위치를 설정하는 메소드

"TranslateTransition".setToX("double");
"TranslateTransition".setToY("double");
"TranslateTransition".setToZ("double");

오토 리버스 설정

"TranslateTransition".setAutoReverse("boolean");

반복 횟수 설정

"TranslateTransition".setCycleCount ( "int");

대충 설정이 되면 마지막으로 TranslateTransition의 “play” 메소드를 호출하여 애니메이션을 시작한다. 또한 도중에 중지하는 “stop” 이나 “pause"라는 메소드도 준비되어 있다. 모두 인수없이 단지 호출만 할 뿐이다.

간단한 사용 예는 다음과 같다.

// import javafx.animation.*;
// import javafx.util.Duration;
 
public void createShape(Pane root){
    Rectangle r = new Rectangle(20, 20, 50, 50);
    r.setFill(Color.CYAN);
    root.getChildren().add(r);
    new TranslateTransition();
     
    TranslateTransition tt = new TranslateTransition(new Duration(1000), r);
    tt.setFromX(20);
    tt.setToX(100);
    tt.setAutoReverse(true);
    tt.setCycleCount(10);
    tt.play();
}

이전까지 동일한 클래스를 이용하여 도형 만들기 위한 메소드 createShape를 다시 바꾸는 형태로 정리하였다. 실행하면 눈에 보이는 사각형이 좌우로 왕복 운동을 한다.

애니메이션을 위한 주요 클래스

TranslateTransition와 같은 애니메이션을 위한 클래스는 그 밖에도 다양하게 준비되어 있다. 여기에서 중요한 것은 정리해 둔다.

리사이즈 애니메이션

new ScaleTransition("Duration", "Node");

설정 메소드

"ScaleTransition".setFromX("double");
"ScaleTransition".setFromY("double");
"ScaleTransition".setFromZ("double");

"ScaleTransition".setToX("double");
"ScaleTransition".setToY("double");
"ScaleTransition".setToZ("double");

회전 애니메이션

new RotateTransition ( "Duration", "Node");

설정 메소드

"RotateTransition".setFromAngle ( "double");
"RotateTransition".setToAngle ( "double");

색상의 애니메이션

new FillTansition("Duration", "Node");
new FillTansition("Duration", "Node", "Color1", "Color2");

new StrokeTransition("Duration", "Node");
new StrokeTransition("Duration", "Node", "Color1", "Color2");

설정 메소드

"StrokeTransition".setFromValue("Color");
"StrokeTransition".setToValue("Color");

페이드 애니메이션

new FadeTransition("Duration", "Node");

설정 용 메소드

"FadeTransition".setFromValue("double");
"FadeTransition".setToValue("double");

기본적인 사용법은 모두 TranslateTransition과 같다. DurationNode를 인수로 지정하여 인스턴스를 만들고, 거기에 있는 메소드를 호출하여 애니메이션을 수행 전후의 값을 각각 설정하고, 그것부터 setAutoReverse과 setCount 등의 조정을 한 후 “play"로 시작 실행한다는 흐름이다.

TranslateTransition를 사용할 수 있게 되면, 이러한 클래스도 거의 같은 감각으로 사용할 수 있게 될 알 수 있다.

Timeline 사용

이전 클래스는 기본적으로 “현재 상태에서 다음 상태로 변화"하는 2개의 상태를 매끄럽게 전환하는 애니메이션을 간단히 만들수 있는 것이다. 더 복잡한 움직임을 실현하려고 이것들을 몇개씩 이어가는 것은 효율적이지 않다.

이러한 경우에 사용되는 것이 “Timeline"라는 클래스이다. Timeline은 문자 그대로 애니메이션의 타임 라인 (시간당 변화를 관리하는 것)이 된다.

이 Timeline을 사용하려면 “KeyFrame"라는 클래스가 필요하다. 이것은 타임 라인에 설정하는 키 프레임 (특정 시간에 애니메이션의 상태를 설정하는 것)이 된다.

Timeline는 먼저 인스턴스를 만들고 거기에 키 프레임이 되는 KeyFrame을 필요에 따라 조합해 간다. 그래서 필요한 설정이 된다면 play 애니메이션을 시작하는 흐름이 된다. 그럼, 애니메이션 작성에 필요한 것들을 정리해 보겠다.

Timeline 만들기

new Timeline();

Timeline 인스턴스는 인수가 없는 디폴트 생성자로 만들 수 있다. 그 자체로는 지금까지의 애니메이션 클래스처럼 Node와 Duration 등은 설정하지 않는다.

KeyFrame 만들기

new KeyFrame("Duration", "KeyValue");

KeyFrame는 인수로 “Duration"과 “KeyValue"라는 인스턴스를 지정한다. Duration은 앞서 등장한 애니메이션의 재생 시간을 처리하는 Duration 인스턴스이다.

KeyValue는 키에 설정하는 값을 처리하는 클래스이다. 이것은 다음과 같이 만든다.

KeyValue 만들기

new keyValue("Property 값");

KeyValue는 속성을 나타내는 “Property"인터페이스를 구현하는 클래스와 거기에 설정되는 값을 인수로 지정한다. 모양의 특성 등은 그 대부분 모든 Property 인터페이스를 구현하여 작성되고, 속성을 나타내는 Property 인스턴스를 꺼내는 메소드가 준비되어 있다. 그것을 이용하여 작업 모양의 작업 속성을 나타내는 Property 인스턴스와 거기에 설정 값을 인수하고 KeyValue를 작성한다.

이것으로 애니메이션에 필요한 “Timeline”, KeyFrame 그리고 KeyFrame에 필요한 KeyValue라는 것이 준비 되었다. 다음에 이를 바탕으로 애니메이션의 정보를 조립해 보도록 하겠다.

Timeline으로 애니메이션 표시

만든 Timeline에는 애니메이션에 관한 다양한 설정을 위한 메소드가 제공되고 있다. 그 메소드들을 사용하여 필요한 정보를 조립하고 있다. 주요 메소드가 정리해 두자.

오토 리버스 설정

"Timeline".setAutoReverse("boolean");

애니메이션을 왕복 재생하는 것디다. true로 하면 오토 리버스가 설정된다.

재생 횟수 설정

"Timeline".setCycleCount("int");

애니메이션의 재생 횟수를 정수로 지정한다.

KeyFrame을 관리하는 List 얻기

"Timeline".getKeyFrames ();

Timeline에 설정되어 있는 KeyFrame는 List (ObservableList) 인스턴스에 정리해 Timeline에 보관되어 있다. 이 List를 얻는하는 것은 getKeyFrames이다.

KeyFrame 추가

"ObservableList".add("KeyFrame");

TimelineKeyFrame을 설정하려면,getKeyFrames에서 List를 얻어 add 메소드로 추가한다. 이것으로 KeyFrame이 추가된다.

그럼, 실제로 Timeline을 사용하여 애니메이션을 샘플을 만들어 보자. 아래에 createShape 메소드를 다시 작성하였다.

// import javafx.animation.*;
// import javafx.util.Duration;
 
public void createShape(Pane root){
    Rectangle r = new Rectangle(20, 20, 100, 50);
    r.setFill(Color.CYAN);
    root.getChildren().add(r);
     
    Timeline tl = new Timeline();
    tl.setAutoReverse(true);
    tl.setCycleCount(10);
 
    // 가로 작업 KeyFrame 작성
    KeyFrame key_a1 = new KeyFrame(
        new Duration(0),
        new KeyValue(r.widthProperty(),100));
    KeyFrame key_a2 = new KeyFrame(
        new Duration(2500),
        new KeyValue(r.widthProperty(),200));
 
    // 채우기 색 작업 KeyFrame 작성
    KeyFrame key_b1 = new KeyFrame(
        new Duration(0),
        new KeyValue(r.fillProperty(),Color.rgb(255, 0, 0)));
    KeyFrame key_b2 = new KeyFrame(
        new Duration(2500),
        new KeyValue(r.fillProperty(),Color.rgb(0, 0, 255)));
    tl.getKeyFrames().add(key_a1);
    tl.getKeyFrames().add(key_a2);
    tl.getKeyFrames().add(key_b1);
    tl.getKeyFrames().add(key_b2);
    tl.play();
}

이것을 실행해 보면, 사각형의 색상이 빨강 ~ 파랑 사이에서 변화하면서 폭이 늘었다가 줄여든다.

여기에서는 Rectangle의 폭 속성을 얻기 위하여 “widthProperty"라는 메소드를 사용한다. 이것은 DoubleProperty라는 double 값의 속성을 얻어온다.

또한 채우기 색을 얻기 위하여 fillProperty라는 메소드를 사용한다. 이것은 ColorProperty이라는 Color를 값으로 하는 Property이다. 인수에는 Color 클래스의 rgb라는 메소드를 사용하여 RGB 각 밝기를 인수로 지정한 색을 설정하고 있다.

Timeline을 잘 다룰 수 있게 되면, 다양한 속성의 값을 자유롭게 조작하고 움직일 수 있게 한다. Node에 어떤 조작 가능한 속성이 있는지 알아 보면 재미있을 것이다.




최종 수정 : 2017-09-19