ユーザーインターフェイス / コンポーネント / アニメーション

アニメーション

アプリケーションの魅力を向上させる方法の1つは、アニメーションを追加することです。 NativeScriptは、アプリケーション内のほぼすべてのネイティブ要素をアニメーション化できる、シンプルで簡単ですが強力なAPIを公開しています。

便宜上、アニメーションを作成する2つの方法 --- 命令型(ui/animationモジュールのAnimationクラス)と宣言型(CSS3キーフレームアニメーション) --- を公開しました。 命令型では、NativeScriptのui/animationモジュールを介してアニメーションメソッドを直接呼び出すことにより、アニメーションを完全に制御できます。 宣言型では、使い慣れたCSS3アニメーションAPIを使用して、CSSキーフレームアニメーションを作成します。 CSSアニメーションvsmの詳細については、このセクションを参照してください。 この記事では、NativeScriptAnimationモジュールの使用方法に関する詳細な情報を提供します。

以下のクラス、インターフェイス、および列挙型は、アプリケーションで明示的に使用できます。

// Main Animation class
const Animation = require("tns-core-modules/ui/animation").Animation;
// Main Animation class
// ALL animating properties at https://docs.nativescript.org/api-reference/interfaces/_ui_animation_.animationdefinition
import {
	Animation,
	AnimationDefinition,
	Pair // Pair: Defines a pair of values (horizontal and vertical) for translate and scale animations.
} from "tns-core-modules/ui/animation";
// AnimationCurveEnum: ease, easeIn, easeInOut, easeOut, linear, spring
const AnimationCurve = require("tns-core-modules/ui/enums").AnimationCurve;
// Full list of animating properties at https://docs.nativescript.org/api-reference/interfaces/_ui_animation_.animationdefinition
const AnimationDefinition = require("tns-core-modules/ui/animation").AnimationDefinition;

// Defines a pair of values (horizontal and vertical) for translate and scale animations.
const Pair = require("tns-core-modules/ui/animation").Pair;

プロパティのアニメーション化

NativeScriptを使用すると、必要な要素のプロパティをアニメーション化できます。 アニメーションの方法のパラメータ(例えばscalerotateduration、など)を設定することにより、プロパティはアニメーション化されます。

NativeScriptでは、次のプロパティをアニメーション化できます。

すべてのアニメーションで、次のプロパティを制御できます。

プロパティ値と利用可能なオプションを以下に定義します。

JAVASCRIPTプロパティ 値の説明
backgroundColor 16進数またはColor値を受け入れます。
curve AnimationCurve列挙体を使用するタイミング関数。
delay アニメーションの開始をミリ秒単位で遅らせます。
duration アニメーションの持続時間をミリ秒単位で指定します。
iterations アニメーションを繰り返す回数。
opacity 数値(0〜1、0は完全な不透明)。
rotate 角度の数値(0〜360度)。
scale 拡大縮小のオブジェクト値 { x:1, y:2 }(1 = 元の倍率)。
translate 移動のオブジェクト値 { x:100, y:200 }(指定されたDIPで移動)。
width 幅。数値。
height 高さ。数値。

次の例では、viewの背景色を「赤」から「緑」に変更します。

view.backgroundColor = new Color("red");
view.animate({
	backgroundColor: new Color("green"),
	duration: 2000
});
view.backgroundColor = new Color("red");
view.animate({
	backgroundColor: new Color("green"),
	duration: 2000
});

次の例は、すべてのプロパティが単一のアニメーションで使用されるテストケースを示しています。

myView.animate({
	backgroundColor: new Color("#414b7d"),
	curve: AnimationCurve.easeOut,
	delay: 300,
	duration: 3000,
	iterations: 3,
	opacity: 0.8,
	rotate: 360,
	scale: {
		x: 2,
		y: 2
	},
	translate: {
		x: 0,
		y: 200
	}
}).then(() => {
	console.log("Animation finished");
}).catch((e) => {
	console.log(e.message);
});
view.animate({
	backgroundColor: new Color("#414b7d"),
	curve: AnimationCurve.easeOut,
	delay: 300,
	duration: 3000,
	iterations: 3,
	opacity: 0.8,
	rotate: 360,
	scale: {
		x: 2,
		y: 2
	},
	translate: {
		x: 0,
		y: 200
	}
}).then(() => {
	console.log("Animation finished");
}).catch((e) => {
	console.log(e.message);
});

デフォルトでは、アニメーションは加速または減速せずに直線速度で移動します。 これは不自然に見え、オブジェクトが最高速度に達するのに時間が必要で、すぐに停止できない現実の世界とは異なる場合があります。 アニメーションカーブ(イージングまたはタイミング関数とも呼ばれる)は、アニメーションに慣性の錯覚を与えるために使用されます。 継続時間の割合を変更することにより、アニメーションの速度を制御します。 NativeScriptには、AnimationCurve列挙体で定義された多数の定義済みアニメーションカーブが付属しています。

NativeScriptでは、アニメーション曲線はAnimationCurve列挙体で表され、アニメーションのcurveプロパティで指定できます。

view.animate({
	translate: {
		x: 0,
		y: 100
	},
	duration: 1000,
	curve: AnimationCurve.easeIn
});
view.animate({
	translate: {
		x: 0,
		y: 100
	},
	duration: 1000,
	curve: AnimationCurve.easeIn
});

NativeScript Playgroundでさまざまなアニメーションタイミング関数を試してみてください

3次ベジェ曲線の2つの制御点のXおよびYコンポーネントを渡すことにより、独自のアニメーション曲線を簡単に作成できます。 ベジェ曲線の使用は、コンピューターグラフィックスで滑らかな曲線を作成するための一般的な手法であり、ベクトルベースの描画ツールで広く使用されています。 cubicBezierメソッドに渡される値は、曲線の形状を制御します。 アニメーションの速度は、結果のパスに基づいて調整されます。

カスタムアニメーションタイミング関数に必要なcubicBezier値を見つけるには、cubic-bezier.comのビジュアルツールを使用してください。 好みのアニメーションパスが見つかったら、キュービックベジェ値をコピーして貼り付け、AnimationCurve.cubicBezier関数に貼り付けます。 この関数には、4つの数字が必要です(アニメーションの2つのポイントそれぞれのX、Y座標)。

view.animate({
	translate: {
		x: 0,
		y: 100
	},
	duration: 1000,
	curve: AnimationCurve.cubicBezier(0.1, 0.1, 0.1, 1)
});
view.animate({
	translate: {
		x: 0,
		y: 100
	},
	duration: 1000,
	curve: AnimationCurve.cubicBezier(0.1, 0.1, 0.1, 1)
});

ターゲットビューをアニメーション化する(または複数のビュー/レイアウトの複雑なアニメーションを作成する)ために、 配列AnimationDefinitionを作成してAnimationコンストラクターに渡すことができます。 定義でtargetプロパティを使用すると、コードを介してアニメーションオブジェクトを完全に制御できます。

const myView = args.object;

const animationDefinition = {
	target: myView, // provide the view to animate
	curve: AnimationCurve.easeOut,
	duration: 1000,
	scale: {
		x: 0.2,
		y: 0.2
	},
	translate: {
		x: -50,
		y: -50
	}
};

animation = new Animation([animationDefinition], false);
animation.play()
	.then(() => {
		console.log("Animation finished");
		console.log("animation.isPlaying: ", animation.isPlaying);
	}).catch((e) => {
		console.log(e.message);
	});
const view = args.object;

const animationDefinition: AnimationDefinition = {
	target: view, // provide the view to animate
	curve: AnimationCurve.easeOut,
	duration: 1000,
	scale: {
		x: 0.2,
		y: 0.2
	},
	translate: {
		x: -50,
		y: -50
	}
};

animation = new Animation([animationDefinition], false);
animation.play()
	.then(() => {
		console.log("Animation finished");
		console.log("animation.isPlaying: ", animation.isPlaying);
	}).catch((e) => {
		console.log(e.message);
	});

cancelメソッドを介してアニメーションをキャンセルします。

animation.cancel();
animation.cancel();

デモソース


連続したアニメーション

アニメーションを接続することにより、1つまたは複数のビューに対して連続したアニメーションのチェーンを作成できます。 このanimateメソッドは、複数のアニメーションをチェーンするために使用できるPromiseを返します。

const duration = 300;
myView.animate({
	opacity: 0,
	duration: duration
}).then(() => myView.animate({
		opacity: 1,
		duration: duration
	})).then(() => myView.animate({
		translate: {
			x: 200,
			y: 200
		},
		duration: duration
	})).then(() => myView.animate({
		translate: {
			x: 0,
			y: 0
		},
		duration: duration
	})).then(() => myView.animate({
		scale: {
			x: 5,
			y: 5
		},
		duration: duration
	})).then(() => myView.animate({
		scale: {
			x: 1,
			y: 1
		},
		duration: duration
	}))
	.then(() => myView.animate({
		rotate: 180,
		duration: duration
	}))
	.then(() => myView.animate({
		rotate: 0,
		duration: duration
	})).then(() => {
		console.log("Animation finished");
	}).catch((e) => {
		console.log(e.message);
	});
const duration = 300;
myView.animate({
		opacity: 0,
		duration: duration
	}).then(() =>
		myView.animate({
			opacity: 1,
			duration: duration
		})
	).then(() =>
		myView.animate({
			translate: {
				x: 200,
				y: 200
			},
			duration: duration
		})
	).then(() =>
		myView.animate({
			translate: {
				x: 0,
				y: 0
			},
			duration: duration
		})
	).then(() =>
		myView.animate({
			scale: {
				x: 5,
				y: 5
			},
			duration: duration
		})
	).then(() =>
		myView.animate({
			scale: {
				x: 1,
				y: 1
			},
			duration: duration
		})
	).then(() =>
		myView.animate({
			rotate: 180,
			duration: duration
		})
	).then(() =>
		myView.animate({
			rotate: 0,
			duration: duration
		})
	).then(() => {
		console.log("Animation finished");
	}).catch(e => {
		console.log(e.message);
	});

デモソース


マルチビューアニメーション

必要に応じて、複数のビューを同時にアニメーション化できます。 すべてのアニメーションを単一の配列に配置し、Animationクラスの助けを借りて再生するのと同じくらい簡単です。

const definitions = [];

const definition1 = {
	target: view1,
	translate: {
		x: 200,
		y: 0
	},
	duration: 1000
};
definitions.push(definition1);

const definition2 = {
	target: view2,
	translate: {
		x: 0,
		y: 200
	},
	duration: 1000
};
definitions.push(definition2);

const definition3 = {
	target: view3,
	translate: {
		x: -200,
		y: 0
	},
	duration: 1000
};
definitions.push(definition3);

const definition4 = {
	target: view4,
	translate: {
		x: 0,
		y: -200
	},
	duration: 1000
};
definitions.push(definition4);

const animationSet = new Animation(definitions);

animationSet.play()
	.then(() => {
		console.log("Animation finished");
	}).catch((e) => {
		console.log(e.message);
	});
const definitions: Array<AnimationDefinition> = [];

const definition1: AnimationDefinition = {
	target: view1,
	translate: {
		x: 200,
		y: 0
	},
	duration: 1000
};
definitions.push(definition1);

const definition2: AnimationDefinition = {
	target: view2,
	translate: {
		x: 0,
		y: 200
	},
	duration: 1000
};
definitions.push(definition2);

const definition3: AnimationDefinition = {
	target: view3,
	translate: {
		x: -200,
		y: 0
	},
	duration: 1000
};
definitions.push(definition3);

const definition4: AnimationDefinition = {
	target: view4,
	translate: {
		x: 0,
		y: -200
	},
	duration: 1000
};
definitions.push(definition4);

const animationSet = new Animation(definitions);

animationSet.play()
	.then(() => {
		console.log("Animation finished");
	}).catch((e) => {
		console.log(e.message);
	});

デモソース


原点のプロパティ

アニメーションをより細かく制御するためにoriginXoriginYプロパティを使用できます。

デフォルトでは、0.5の値(X座標とY座標の両方)はビューの理想的な中心に配置しています。 複雑な回転アニメーションを作成するために、原点のプロパティを変更できます。 以下の例では、異なるoriginXおよびoriginYポイントに対してビューを回転させる方法を示しています。

function animate() {
	// myFirstView.originX = 0.5; // Default value (center of the view's horizontal axis)
	// myFirstView.originY = 0.5; // Default value (middle of the view's vertical axis)
	myFirstView.animate({
		rotate: 360,
		duration: 3000
	}).then(() => {
		myFirstView.rotate = 0;
	}).catch((e) => {
		console.log(e.message);
	});

	mySecondView.originX = 1; // most right of horizontal axis
	mySecondView.animate({
		rotate: 360,
		duration: 3000
	}).then(() => {
		mySecondView.rotate = 0;
	}).catch((e) => {
		console.log(e.message);
	});

	myThirdView.originX = 0; // most left of horizontal axis
	myThirdView.animate({
		rotate: 360,
		duration: 3000
	}).then(() => {
		myThirdView.rotate = 0;
	}).catch((e) => {
		console.log(e.message);
	});

	myForthView.originY = 1; // bottom of vertical axis
	myForthView.animate({
		rotate: 360,
		duration: 3000
	}).then(() => {
		myForthView.rotate = 0;
	}).catch((e) => {
		console.log(e.message);
	});

	myFifthView.originY = 0; // top of vertical axis
	myFifthView.animate({
		rotate: 360,
		duration: 3000
	}).then(() => {
		myFifthView.rotate = 0;
	}).catch((e) => {
		console.log(e.message);
	});
}
exports.animate = animate;
export function animate() {
	// myFirstView.originX = 0.5; // Default value (center of the view's horizontal axis)
	// myFirstView.originY = 0.5; // Default value (middle of the view's vertical axis)
	myFirstView.animate({
		rotate: 360,
		duration: 3000
	}).then(() => {
		myFirstView.rotate = 0;
	}).catch((e) => {
		console.log(e.message);
	});

	mySecondView.originX = 1; // most right of horizontal axis
	mySecondView.animate({
		rotate: 360,
		duration: 3000
	}).then(() => {
		mySecondView.rotate = 0;
	}).catch((e) => {
		console.log(e.message);
	});

	myThirdView.originX = 0; // most left of horizontal axis
	myThirdView.animate({
		rotate: 360,
		duration: 3000
	}).then(() => {
		myThirdView.rotate = 0;
	}).catch((e) => {
		console.log(e.message);
	});

	myForthView.originY = 1; // bottom of vertical axis
	myForthView.animate({
		rotate: 360,
		duration: 3000
	}).then(() => {
		myForthView.rotate = 0;
	}).catch((e) => {
		console.log(e.message);
	});

	myFifthView.originY = 0; // top of vertical axis
	myFifthView.animate({
		rotate: 360,
		duration: 3000
	}).then(() => {
		myFifthView.rotate = 0;
	}).catch((e) => {
		console.log(e.message);
	});
}
<GridLayout rows="auto, *, *, *, *" columns="*, *" backgroundColor="white">
	<Button row="0" col="0" colSpan="2" text="Animate" tap="animate" class="btn btn-primary btn-active" />
	<GridLayout row="1" col="0" colSpan="2" id="myFirstView" automationText="myFirstView" width="400" height="40" >
		<Label text="Default originX / originY (0.5)" horizontalAlignment="center"/>
	</GridLayout>
	<GridLayout row="2" col="0" colSpan="2" id="mySecondView" automationText="mySecondView" width="400" height="40" >
		<Label text="originX = 1"  horizontalAlignment="right"/>
	</GridLayout>
	<GridLayout row="3" col="0" colSpan="2" id="myThirdView" automationText="myThirdView" width="400" height="40" >
		<Label text="originX = 0"  horizontalAlignment="left"/>
	</GridLayout>
	<GridLayout row="4" col="0" id="myForthView" automationText="myForthView" width="100" height="300" >
		<Label text="originY = 1" verticalAlignment="bottom"/>
	</GridLayout>
	<GridLayout row="4" col="1" id="myFifthView" automationText="myFifthView" width="100" height="300" >
		<Label text="originY = 0" verticalAlignment="top"/>
	</GridLayout>
</GridLayout>

デモソース


幅 & 高さプロパティ

{N} 6.0以降、ビューのwidthおよびheightプロパティをアニメーション化できます。 以下の例で、これらのアニメーションを構成する方法を示します。

const AnimationCurve = require("tns-core-modules/ui/enums").AnimationCurve;

function animateWidth(args) {
	const button = args.object;
	const page = button.page;
	const myView = page.getViewById("lbl");

	myView.animate({
		width:320,
		duration: 1000,
		curve: AnimationCurve.easeIn
	});
}
exports.animateWidth = animateWidth;

function animateHeight(args) {
	const button = args.object;
	const page = button.page;
	const myView = page.getViewById("lbl");

	myView.animate({
		height:400,
		duration: 1000,
		curve: AnimationCurve.easeIn
	});
}
exports.animateHeight = animateHeight;
import { AnimationCurve } from "tns-core-modules/ui/enums";
import { View } from "tns-core-modules/ui/core/view";

export function animateWidth(args) {
	let button = args.object;
	let page =  button.page;
	let view = <View>page.getViewById("lbl");

	view.animate({
		width: 320,
		duration: 1000,
		curve: AnimationCurve.easeIn
	});
}

export function animateHeight(args) {
	let button = args.object;
	let page =  button.page;
	let view = <View>page.getViewById("lbl");

	view.animate({
		height: 400,
		duration: 1000,
		curve: AnimationCurve.easeIn
	});
}
<GridLayout rows="auto, auto, *">
	<Button row="0" text="Animate height" tap="animateHeight" class="btn btn-primary btn-active" width="80%"/>
	<Button row="1" text="Animate width" tap="animateWidth" class="btn btn-primary btn-active" width="80%"/>
	<Label row="2" id="lbl" text="NativeScript" textWrap="true" marginTop="50"/>
</GridLayout>

デモソース


APIリファレンス

名前 タイプ
Animation Class
CubicBezierAnimationCurve Class
AnimationDefinition Interface
Cancelable Interface
Pair Interface
AnimationCurve Enum

参照: CSSアニメーション

入門

コアコンセプト

ユーザーインターフェース

ツール

ハードウェアアクセス

プラグインの開発

リリース

アプリテンプレート

パフォーマンスの最適化

フレームワークモジュール

ガイド

サポートを受ける

トラブルシューティング

Siedkick