アプリケーションの魅力を向上させる方法の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を使用すると、必要な要素のプロパティをアニメーション化できます。 アニメーションの方法のパラメータ(例えばscale、rotate、duration、など)を設定することにより、プロパティはアニメーション化されます。
NativeScriptでは、次のプロパティをアニメーション化できます。
opacity
backgroundColor
translateX
, translateY
scaleX
, scaleY
rotate
width
, height
すべてのアニメーションで、次のプロパティを制御できます。
duration
:アニメーションの長さ。delay
:アニメーションの開始を遅らせる時間。 iterations
:アニメーションを再生する回数を指定します。 curve
:アニメーションの速度曲線。プロパティ値と利用可能なオプションを以下に定義します。
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列挙体で定義された多数の定義済みアニメーションカーブが付属しています。
linear
:最も単純なアニメーションカーブは線形です。アニメーションの実行中は一定の速度を維持します。easeIn
:ease-in カーブにより、アニメーションの開始が遅くなり、進行に合わせて速度が上がります。easeOut
:ease-out カーブを使用すると、アニメーションがすばやく開始され、完了するにつれ速度が低下します。easeInOut
:ease-in-out カーブを使用すると、アニメーションの開始が遅くなり、継続時間の途中で加速し、完了前に再び遅くなります。spring
:スプリングアニメーションカーブにより、アニメーションはスプリング(バウンス)エフェクトを生成します。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メソッドを介してアニメーションをキャンセルします。
アニメーションを接続することにより、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);
});
アニメーションをより細かく制御するためにoriginX、originYプロパティを使用できます。
デフォルトでは、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>
名前 | タイプ |
---|---|
Animation | Class |
CubicBezierAnimationCurve | Class |
AnimationDefinition | Interface |
Cancelable | Interface |
Pair | Interface |
AnimationCurve | Enum |
参照: CSSアニメーション