Custom Curve
Mapray ではアニメーションをカスタマイズするために、独自の Curve を実装することができます。
ここでは、独自の CosCurve クラスを実装して、コサイン動作を行うアニメーションを実装する例を示します。
Curve のサブクラス化
独自の Curve クラスを作成するには、以下の3つのメソッドをオーバライドする必要があります。
-
isTypeSupported( type )
クラスがサポートしている型を返します
-
getValue( time, type )
指定時刻 (time) での値を指定した型 (type) で返します。 Binder に渡される値がこの値となります。
-
getInvariance( interval )
指定された区間 (interval) に対して Curve の値が一定となる区間 (Invariance) を返します。
CosCurve の実装例
コサイン動作を行う Custom Curve (CosCurve) の実装例を以下に示します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 | class CosCurve extends mapray.animation.Curve {
constructor( type ) {
super();
if ( type !== mapray.animation.Type.find("number") ) {
throw new mapray.animation.AnimationError( "unsupported type" );
}
this._value_type = type;
this._ratio = 1.0;
this._base_value = 1.0;
this._value_ratio = 1.0;
}
setRatio( ratio ) { this._ratio = ratio; }
setBaseValue( value ) { this._base_value = value; }
setValueRatio( ratio ) { this._value_ratio = ratio; }
/** @override */
isTypeSupported( type ) {
return type.isConvertible( this._value_type );
}
/** @override */
getValue( time, type ) {
const theta = (time.toNumber() * this._ratio + 180) * mapray.GeoMath.DEGREE;
const value = (Math.cos(theta) + 1) * 0.5 * this._value_ratio + this._base_value;
return type.convertValue( this._value_type, value );
}
/** @override */
getInvariance( interval ) {
return new mapray.animation.Invariance();
}
}
|
Interval と Invariance
getInvariance の実装
Curve の値が一定となる時刻区間を Invariance を利用して表明します。
-
全域可変
Curve の値が常に変化する場合、不変区間がないため、 Invariance をそのまま return します。
| getInvariance( interval ) {
return new mapray.animation.Invariance();
}
|
-
全域不変
Curve の値が一定(例: ConstantCurve)の場合、 mapray.animation.Interval.UNIVERSAL を使用します。
| getInvariance( interval ) {
const invariance = new mapray.animation.Invariance();
return invariance.write( mapray.animation.Interval.UNIVERSAL );
}
|
-
不変区間を指定する
KFLinearCurve のように、特定の時刻区間でのみ関数値が不変の場合、次のように指定します。
| getInvariance( interval ) {
const ival_inner = new mapray.animation.Interval( first_time, last_time, true, true );
const invr_full = new mapray.animation.Invariance();
invr_full.write( ival_inner.getPrecedings() ); // The time of the first key and the interval before it.
invr_full.write( ival_inner.getFollowings() ); // The time of the last key and the interval after it.
// Narrow the range of the interval to return.
return invr_full.getNarrowed( interval );
}
|
CosCurve では、Curve の値が常に変化し続けるため、空の Invariance オブジェクトを返します。
サンプルコード
独自の CosCurve を実装し、コサイン動作のアニメーションを行う例を示します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 | <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://resource.mapray.com/mapray-js/v0.9.6/mapray.min.js"></script>
<script src="https://resource.mapray.com/ui/v0.9.6/maprayui.min.js"></script>
<link rel="stylesheet" href="https://resource.mapray.com/styles/v1/mapray.css">
<style>
html, body, div#mapray-container { margin: 0; padding: 0; height: 100%; }
</style>
</head>
<body>
<div id="mapray-container"></div>
</body>
</html>
<script>
class CosCurve extends mapray.animation.Curve {
constructor( type ) {
super();
if ( type !== mapray.animation.Type.find("number") ) {
throw new mapray.animation.AnimationError( "unsupported type" );
}
this._value_type = type;
this._ratio = 1.0;
this._base_value = 1.0;
this._value_ratio = 1.0;
}
setRatio( ratio ) { this._ratio = ratio; }
setBaseValue( value ) { this._base_value = value; }
setValueRatio( ratio ) { this._value_ratio = ratio; }
/** @override */
isTypeSupported( type ) {
return type.isConvertible( this._value_type );
}
/** @override */
getValue( time, type ) {
const theta = (time.toNumber() * this._ratio + 180) * mapray.GeoMath.DEGREE;
const value = (Math.cos(theta) + 1) * 0.5 * this._value_ratio + this._base_value;
return type.convertValue( this._value_type, value );
}
/** @override */
getInvariance( interval ) {
return new mapray.animation.Invariance();
}
}
class CustomViewer extends maprayui.StandardUIViewer {
constructor( container, apikey ) {
super( container, apikey);
const pinEntity = new mapray.PinEntity( this.viewer.scene );
pinEntity.addPin( new mapray.GeoPoint( 139.699985, 35.690777, 40 ), { id: "pin", size: 40, bg_color: [1, 0, 0] });
this.viewer.scene.addEntity( pinEntity );
const pinEntry = pinEntity.getEntry( "pin" );
// Create cosine curve.
const curve = new CosCurve( mapray.animation.Type.find( "number" ) );
curve.setRatio( 30 );
curve.setBaseValue( 10 );
curve.setValueRatio( 80 );
// Create updater.
this.totalTime = 0;
this.isAnimationStart = false;
this.updater = new mapray.animation.Updater();
// Bind "size" and "bg_color" param to updater and curve.
pinEntry.animation.bind( "size", this.updater, curve );
}
/** @override */
onUpdateFrame( delta_time ) {
super.onUpdateFrame( delta_time );
if ( this.isAnimationStart ) {
this.totalTime += delta_time;
this.updater.update( mapray.animation.Time.fromNumber( this.totalTime ) );
}
}
startAnimation() {
this.totalTime = 0;
this.isAnimationStart = true;
console.log( "start animation" );
}
}
// Set up your API Key, which can be created in Mapray Cloud.
const apikey = "<YOUR_MAPRAY_API_KEY>";
const uiviewer = new CustomViewer( "mapray-container", apikey);
uiviewer.setCameraPosition({
longitude: 139.697475,
latitude: 35.682494,
height: 420
});
uiviewer.setLookAtPosition({
longitude: 139.699985,
latitude: 35.690777,
height: 35
});
uiviewer.startAnimation();
</script>
|