コンテンツにスキップ

Custom Curve

Mapray ではアニメーションをカスタマイズするために、独自の Curve を実装することができます。

ここでは、独自の CosCurve クラスを実装して、コサイン動作を行うアニメーションを実装する例を示します。

Curve のサブクラス化

独自の Curve クラスを作成するには、以下の3つのメソッドをオーバライドする必要があります。

  1. isTypeSupported( type )

    クラスがサポートしている型を返します

  2. getValue( time, type )

    指定時刻 (time) での値を指定した型 (type) で返します。 Binder に渡される値がこの値となります。

  3. 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

  • Interval

    アニメーション時刻の区間を表現するクラスです。時刻は mapray.animation.Time.fromNumber で指定します。

    1
    2
    3
    const first = mapray.animation.Time.fromNumber(0);
    const last = mapray.animation.Time.fromNumber(11);
    const ival_inner = new mapray.animation.Interval( first, last, true, true );
    
  • Invariance

    Curve のサブクラスの実装者が、Curve の値が一定となる時刻区間を表明するために利用するクラスです。 値が一定となる部分を定義します。

getInvariance の実装

Curve の値が一定となる時刻区間を Invariance を利用して表明します。

  • 全域可変

    Curve の値が常に変化する場合、不変区間がないため、 Invariance をそのまま return します。

    1
    2
    3
    getInvariance( interval ) {
        return new mapray.animation.Invariance();
    }
    
  • 全域不変

    Curve の値が一定(例: ConstantCurve)の場合、 mapray.animation.Interval.UNIVERSAL を使用します。

    1
    2
    3
    4
    getInvariance( interval ) {
        const invariance = new mapray.animation.Invariance();
        return invariance.write( mapray.animation.Interval.UNIVERSAL );
    }
    
  • 不変区間を指定する

    KFLinearCurve のように、特定の時刻区間でのみ関数値が不変の場合、次のように指定します。

    1
    2
    3
    4
    5
    6
    7
    8
    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>

Info

このサンプルコードは、<YOUR_MAPRAY_API_KEY>を、あなたのMapray CloudアカウントのAPI Keyに置き換えるまで、期待通りに動作しません。