Bounce: Nested Timeline Animation
JavaFx의 Timeline을 사용하면 시간에 따른 객체들에게 애니메이션이 가능해진다. 보통 한번에 한가지만 움직이겠지만, Timeline은 더 복잡한 애니메이션들을 만들수 있게, 내재된(nested) timeline들을 실제로 지원한다. 이 예제에서는 3개의 내재된 timeline을 포함한 master timeline을 볼 수 있다: 앞 뒤로 움직이는 것, 위 아래로 움직이는 것, 그리고 공이 바닥에 충돌시 찌그러뜨리는 것.
코드 이해하기
이 예제의 모델은 아주 간단하다. 공은 4개의 변수로 정의된다: x, y, sx, 그리고 sy. x 그리고 y 변수들은 볼의 현재 위치를 나타낸다. sx 와 sy 는 공의 x 비율과 y 비율이다. 바닥에 공이 부딫혔을 때 찌그러뜨리는 것을 보여주게 한다.
//width and height of the screen var w = 240; var h = 320; // model variables def rad = 50; // radius of the ball var x = 0.0; // x location of the ball var y = 0.0; // y location of the ball var sx = 1.0; // scale x var sy = 1.0; // scale y var color1 = Color.SILVER; var color2 = Color.MAROON;
그림 1: 공 데이터 모델
공을 각각 다른 방향으로 움직이는 개별적인 timeline이 있다. ax timeline은 공을 옆으로 10초 넘게 움직인다. ay timeline은 4.5초 마다 공을 위 아래로 움직인다. 더 부드럽게 튀어오르는 움직임을 만들기 위해 SPLINE interpolator 를 사용한다. 세번째 timeline의, sxy는, 공이 바닥 근처에 접근했을때 실제로 찌그러지는 것을 수행한다.
// animate side to side
var ax = Timeline {
keyFrames:[
KeyFrame { time: 0s values: x => rad },
KeyFrame { time: 3s values: x => w-rad tween Interpolator.LINEAR },
]
autoReverse: true
repeatCount: Timeline.INDEFINITE
}
// animate up and down
var ay = Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames: [
KeyFrame { time: 0s values: y => 0.0 },
KeyFrame { time: 2.2s values: y => h-rad tween Interpolator.SPLINE(0,0,.5,0) },
KeyFrame { time: 2.25s values: y => h-rad },
KeyFrame { time: 4.5s values: y => 0.0 tween Interpolator.SPLINE(0,0,0,0.5) },
]
}
// animate the squish when boucing
var sxy = Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames: [
KeyFrame { time: 2s values: [sx => 1.0, sy => 1.0 ] },
KeyFrame { time: 2.25s
values: [
sx => 1.2 tween Interpolator.LINEAR,
sy => 0.7 tween Interpolator.LINEAR,
]
},
KeyFrame { time: 2.5s
values: [
sx => 1.0 tween Interpolator.LINEAR,
sy => 1.0 tween Interpolator.LINEAR,
]
},
KeyFrame { time: 4.5s
values: [
sx => 1.0 tween Interpolator.LINEAR,
sy => 1.0 tween Interpolator.LINEAR,
]
},
]
}
그림 2: 공 움직임 Timelines
3개의 timeline들은 무한 반복을 하는, clip 라는 master timline에 함께 포함된다.
// loop the other timelines forever
var clip = Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames:
KeyFrame {
time: 0s
timelines: [ax, ay, sxy]
}
}
그림 3: Master Timeline
이제 데이터 모델이 정확히 움직였다면 그림 4처럼, 공을 만들기 위해 그림자진 원을 만들 수 있다. 공은 지름이 50이고 그림자 효과를 내기 위해 RadialGradient을 사용하여 채운 Circle 이다. 공을 움직이는 원의 transforms 변수는 순차적인 4개의 변형들에 묶여있다. 첫번째는 공을 움직인다. 두번째로 공의 중심을 변형(해석)하면 세번째 변형이 정확히 찌그러뜨리는 것을 수행할 것이다. 네번재 변형은 단순히 두번째 것을 되돌린다.
Circle {
centerX: 0 centerY: 0 radius: rad
stroke: Color.BLACK
fill: RadialGradient {
proportional: false radius: 70
centerX: 0 centerY: 0
focusX: 20 focusY: -50
stops: [
Stop { offset: 0.0 color: color1 },
Stop { offset: 0.85 color: color2 },
Stop { offset: 1.0 color: color2 }
]
}
transforms: bind [
Transform.translate(x, y), // move left and right and up and down
Transform.translate(50.0, 50.0), // translate to the center of the ball
Transform.scale(sx, sy), // do the squish
Transform.translate(-50.0, -50.0) // un-translate
]
}
그림 4: 실제 공
Josh MarinacciStaff Engineer,
Sun Microsystems
