前回は基本的なアニメーションということで、
今回、
なお、
移動、拡大・縮小、そして回転
前回のサンプルで移動のアニメーションを使用したように、
そのため、
これらのクラスのスーパークラスであるTransitionクラスはnodeアトリビュートを持ちます。このnodeアトリビュートが回転や移動の対象となります。
var node: Node = Group { ... };
var rotateTransition = RotateTransition {
// 回転の対象ノード
node: node
// 回転角度の設定
// 0度から720度回転させる
fromAngle: 0
byAngle: 720
// これらのアトリビュートは Timeline クラスに準ずる
duration: 5s
repeatCount:4
interpolate: Interpolator.EASEBOTH
autoReverse: true
};
// 回転の開始
rotateTransition.play();
回転の角度を設定するには、
回転の中心はノードの中心です。もしノードの中心以外の点を回転中心にしたい場合は、
durationアトリビュートやrepeatCountアトリビュートなどはTimelineクラスを使用した時と同じです。補間方法はKeyFrameクラスではtween演算子を使用しましたが、
最後にアニメーションを開始させるため、
次にノードを表示する部分を示します。
Stage {
title: "Rotate Sample"
scene: Scene {
width: 200
height: 200
content: [
node
]
}
}
特に難しい部分は何もありません。単に変数nodeを描画しているだけです。ここでは変数nodeは6つの円としました。
def radian = Math.PI / 180.0;
var node: Node = Group {
translateX: 100
translateY: 100
// 6個の円
content: [
for (angle in [0..300 step 60]) {
Circle {
centerX: 50.0 * Math.cos(angle * radian);
centerY: -50.0 * Math.sin(angle* radian);
radius: 35
fill: Color.PINK
stroke: Color.RED
}
},
// 重ね順を調節するための半円
Arc {
centerX: 50,
centerY: 0
radiusX: 35,
radiusY: 35
startAngle: 180,
length: 180
type: ArcType.OPEN
fill: Color.PINK
stroke: Color.RED
}
]
};
最後のArcオブジェクトがないと、
実行結果を図1に示します。いつもと同じようにこの図もアプレットページへのリンクになっています。これ以降も実行結果の図はアプレットのページへのリンクになっています。また、
フェードイン、フェードアウト
次に行うのが、
var fadeTransition = FadeTransition {
// フェードの対象となるノード
node: blurredStar
// 不透明度を 0.3 から 1.0 まで変化させる
fromValue: 0.3
toValue: 1.0
duration: 0.5s
repeatCount: Timeline.INDEFINITE
autoReverse: true
};
fadeTransition.play();
フェードイン、
他のアトリビュートはRotateTransitionクラスと同じです。ここでは、
星形を作るにはjavafx.
ぼかしを行うにはNodeクラスのeffectアトリビュートを使用します。effectアトリビュートの型はjavafx.
以下に星形と星形をぼかしたノードを作成するスクリプトを示します。
// 星の形を表す PathElement
var starElements: PathElement[] = [
MoveTo { x: 0 y: -50 },
LineTo { x: 11.803 y: -11.804 },
LineTo { x: 50 y: -11.804 },
LineTo { x: 19.098 y: 11.804 },
LineTo { x: 30.902 y: 50 },
LineTo { x: 0 y: 26.394 },
LineTo { x: -30.902 y: 50 },
LineTo { x: -19.098 y: 11.804 },
LineTo { x: -50 y: -11.804 },
LineTo { x: -11.803 y: -11.804 },
ClosePath {}
];
// 星形
var star: Node = Path {
translateX: 100
translateY: 100
fill: Color.web("#CCCC00")
stroke: null
elements: starElements
};
// ぼかした星形
var blurredStar: Node = Path {
translateX: 100
translateY: 100
fill: Color.web("#FFFF00")
stroke: null
// ぼかしをかける
effect: GaussianBlur {
radius: 20
}
elements: starElements
};
星形を表すPathElementオブジェクトのシーケンスは、
最後に星形と星形のぼかしを描画する部分を示します。
Stage {
title: "Fading Sample"
scene: Scene {
width: 200
height: 200
fill: LinearGradient {
startX: 0.0, startY: 0.0, endX: 0.0, endY: 1.0
proportional: true
stops: [
Stop { offset: 0.0 color: Color.web("#000022") },
Stop { offset: 1.0 color: Color.web("#000066") }
]
}
content: [blurredStar, star]
}
}
夜空を表すため、
では、
パスに沿った移動
今まで扱ってきた移動のアニメーションは移動元の座標から、
もちろん、
Adobe Flashではモーションガイドと呼ばれるパスを設定して、
アニメーションのガイドとなるパスはjavafx.
これをスクリプトで表すと次のようになります。アニメーションはガイドパスの起点から終点までアニメーションしながら移動します。残念ながら、
// パスに沿って移動するノード
var node: Node = ...
// ガイドとなるパス
var guidePath = Path { ... }
var pathTransition = PathTransition {
node: node
path: AnimationPath.createFromPath(guidePath)
}
// アニメーションの開始
pathTransition.play();
ここでは花をらせんに沿って移動させてみました。
花は花びらを作成し、
var node: Node = Group {
content: [
// 90 度ずつ回転させた花びらを 4 枚
for (angle in [0, 90, 180, 270]) {
Path {
stroke: null
fill: RadialGradient {
centerX: 0.5 centerY: 1.0
stops: [
Stop { offset: 0.0 color: Color.web("#FFEEEE") },
Stop { offset: 0.8 color: Color.PINK }
]
}
// (0, 0) を中心に回転
transforms: Rotate { pivotX: 0.0 pivotY: 0.0 angle: angle }
elements: [
MoveTo { x: 0 y: 0},
CubicCurveTo {
x: 7.321 y: -12.68
controlX1: 0 controlY1: 0
controlX2: 7.321 controlY2: -8.68
},
ArcTo {
x: -7.321 y: -12.68
radiusX: 7.32 radiusY: 7.32
},
CubicCurveTo {
x: 0 y: 0
controlX1: -7.321 controlY1: -8.68
controlX2: 0 controlY2: 0
},
]
}
}
]
}
ガイドとなるパスはらせんにしました。いわゆる蚊取り線香のようならせんで、
以下にらせんを作成している部分を示します。角度を15度で分割し、
// 度からラジアンへの変換係数
def TO_RADIAN = Math.PI/180.0;
// node を移動させるガイドパス
var guidePath = Path {
elements: [
MoveTo { x: 100 y: 100 },
for (deg in [0.0..1800.0 step 15.0]) {
// 度からラジアンに変換
var rad = deg * TO_RADIAN;
LineTo {
x: 2.0 * rad * Math.sin(rad) + 100
y: 2.0 * rad * Math.cos(rad) + 100
}
}
]
}
Stageオブジェクトを作成する部分は今までのサンプルと同じなので、
var pathTransition = PathTransition {
// パスに沿って移動する対象ノード
node: node
// パスから AnimationPath オブジェクトを作成
path: AnimationPath.createFromPath(guidePath)
// パスに沿って回転
orientation: OrientationType.ORTHOGONAL_TO_TANGENT
duration: 10s
repeatCount:4
autoReverse: true
}
pathTransition.play();
赤字で示したorientationアトリビュートはノードがパスに沿って移動する時に、
パスに沿って回転させる場合は、
複数のアニメーションを順番に行う
ここまでは単体のアニメーションを扱ってきましたが、
この2つのクラスの違いは、
そこで、
SequentialTransitionクラスはcontentアトリビュートを持ちます。contentアトリビュートの型はTransitionクラスのシーケンスであり、
たとえば、
var seqTransition = SequentialTransition {
// アニメーションの対象となるノード
node: node
// シーケンシャルに実行するアニメーション
content: [
TranslateTransition {
duration: 2s
fromX: 20
fromY: 20
toX: 100
toY: 100
},
RotateTransition {
duration: 1s
fromAngle: 0
byAngle: 360
},
ScaleTransition {
duration: 2s
byX: 2
byY: 2
}
]
}
seqTransition.play();
SequentailTransitionクラスのnodeアトリビュートが、
また、
ここでは、
以下にSequentialAnimationクラスを使用する部分を示します。
var seqTransition = SequentialTransition {
// アニメーションの対象となるノード
node: star
// シーケンシャルに実行されるアニメーション
content: [
TranslateTransition {
duration: 2s
fromX: 20
fromY: 20
toX: 180
toY: 20
},
PauseTransition {
duration: 0.5s
},
RotateTransition {
duration: 1s
fromAngle: 0
byAngle: 360
},
TranslateTransition {
duration: 2s
fromX: 180
fromY: 20
toX: 180
toY: 180
},
PauseTransition {
duration: 0.5s
},
RotateTransition {
duration: 1s
fromAngle: 0
byAngle: 360
},
TranslateTransition {
duration: 2s
fromX: 180
fromY: 180
toX: 20
toY: 180
},
PauseTransition {
duration: 0.5s
},
RotateTransition {
duration: 1s
fromAngle: 0
byAngle: 360
},
TranslateTransition {
duration: 2s
fromX: 20
fromY: 180
toX: 20
toY: 20
},
PauseTransition {
duration: 0.5s
},
RotateTransition {
duration: 1s
fromAngle: 0
byAngle: 360
}
]
}
seqTransition.play();
このスクリプトでは星形を移動、
ここで、
もし、
Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames : [
KeyFrame {
time : 0s
action : function() {
seqTransition.playFromStart();
}
},
KeyFrame {
time : 14s
}
]
}.play();
14秒にKeyFrameオブジェクトがあるのは、
実行結果を図4に示します。
複数のアニメーションを同時に行う
今度は複数のアニメーションを同時に行ってみます。ParallelTransitionクラスの使い方はSequentialTransitionとほぼ同じです。しかし、
先ほど作成した花がらせん状に移動するスクリプトは花の回転がちょっと少なすぎたように感じるので、
var parTransition = ParallelTransition {
node: node
content: [
// らせんに沿って移動
PathTransition {
path: AnimationPath.createFromPath(guidePath)
orientation: OrientationType.ORTHOGONAL_TO_TANGENT
duration: 10s
repeatCount: 2
autoReverse: true
interpolate: Interpolator.EASEBOTH
},
// 回転
RotateTransition {
fromAngle: 0
byAngle: 1800
duration: 10s
repeatCount: 2
autoReverse: true
interpolate: Interpolator.EASEBOTH
},
// 拡大
ScaleTransition {
byX: 1.5
byY: 1.5
duration: 10s
repeatCount: 2
autoReverse: true
interpolate: Interpolator.EASEBOTH
}
]
}
parTransition.play();
ParallelTransitionクラスもSequentialTransitionクラスと同様duration、
上述のスクリプトではすべてアニメーションの時間が10秒なので、
回転しながららせんに沿って移動する花の実行結果を図5に示しました。
モーフィング
最後におまけ的なアニメーションを紹介しましょう。モーフィングとは2つの形状を自然に変形させることをいいます。
JavaFXでは簡単なモーフィングを行うためにjavafx.
とはいえ、
DelegateShapeクラスは単独で使用するのではなく、
var rectangle = Rectangle {
x: -50 y: -50 width: 100 height: 100
}
var circle = Circle {
centerX: 0 centerY: 0 radius: 40
}
var shape: Shape;
Stage {
title: "Morphing"
scene: Scene {
width: 200 height: 200
content: DelegateShape {
// モーフィングする対象
shape: bind shape
translateX: 100 translateY: 100
fill: Color.RED
}
}
}
Timeline {
keyFrames: [
KeyFrame {
time: 0s values: shape => rectangle
},
KeyFrame {
time: 5s values: shape => circle
}
]
}.play();
DelegateShapeクラスはshapeアトリビュートを持ち、
そして、

DelegateShapeクラスを使う時の注意点として、
では、
ところで、
ここでは、
var shape: Shape;
var color: Color;
Stage {
title: "Morphing Sample"
scene: Scene {
width: 200
height: 200
fill: LinearGradient {
startX: 0.0, startY: 0.0, endX: 0.0, endY: 1.0
proportional: true
stops: [
Stop { offset: 0.0 color: Color.WHITE },
Stop { offset: 0.5 color: Color.LIGHTGRAY }
]
}
content: DelegateShape {
// モーフィングする対象
shape: bind shape
// 色もいっしょに変更する
fill: bind color
// ドロップシャドウ
effect: DropShadow {
offsetX: 5
offsetY: 5
radius: 5
}
translateX: 100
translateY: 100
}
}
}
var timeline = Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames: [
KeyFrame {
// 星
time: 0s
values: [
shape => star,
color => Color.YELLOW
]
},
KeyFrame {
// 星から花
time: 5s
values: [
shape => flower,
color => Color.PINK
]
},
KeyFrame {
// 花から丸
time: 10s
values: [
shape => circle,
color => Color.RED,
]
},
KeyFrame {
// 丸から星
time: 15s
values: [
shape => star,
color => Color.YELLOW
]
}
]
};
timeline.play();
星から花、
このように、
さて、