0

I'm trying to replicate this Azure Maps example, and I have everything working except the marker arrow, which isn't moving. When I provide a map, the camera animates correctly, but the arrow icon remains stationary.

The Atlas library and atlas.animations are present in the browser on runtime, and I am not receiving any console errors from the libraries. Any assistance would be appreciated.

The azure-maps-animations.js used is from the last official release. (I changed azmaps to atlas, but that's beside the point because animation librari is working and present in browser console).

Here it is the HTML code:

<div #myMap style="position:relative;width:100%;min-width:290px;height:600px;"></div>

<div style="position:absolute;top:15px;left:15px;border-radius:5px;padding:5px;background-color:white;">
  <button (click)="play()">Play</button>
  <button (click)="pause()">Pause</button>
  <button (click)="stop()">Stop</button>
  <button (click)="reset()">Reset</button>
  <br/><br/>
  Follow: <input type="checkbox" (click)="toggleFollow()" title="Follow" checked/><br/>
  Follow offset: <input type="checkbox" (click)="toggleFollowOffset()" title="Follow offset"/><br/>
  Loop: <input type="checkbox" (click)="toggleLooping()" title="Loop"/><br/>
  Reverse: <input type="checkbox" (click)="toggleReverse()" title="Reverse"/>
</div>

<fieldset style="width:calc(100% - 30px);min-width:290px;margin-top:10px;">
  <legend>Animate along a route path</legend>
  This sample shows how to smoothly animate a symbol along a route path taking into consideration timestamps for each point in the route path.
  This sample also includes controls and options for the animation.
  This sample uses the open source <a href="https://github.com/Azure-Samples/azure-maps-animations" target="_blank" title="Azure Maps Animation module">Azure Maps Animation module</a>
</fieldset>

And the typescript code (it's an angular component):

import { Component, ElementRef, ViewChild } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import atlas from 'azure-maps-control';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet],
  templateUrl: './app.component.html',
  styleUrl: './app.component.scss',
})
export class AppComponent {
  @ViewChild('myMap', { static: true }) myMap!: ElementRef;

  map!: atlas.Map;
  pin!: atlas.Shape;
  lineSource!: atlas.source.DataSource;
  pinSource!: atlas.source.DataSource;
  animation!: any;

  routePoints = [
    new atlas.data.Feature(new atlas.data.Point([-122.34758, 47.62155]), { _timestamp: new Date('Tue, 18 Aug 2020 00:53:53 GMT').getTime() }),
    new atlas.data.Feature(new atlas.data.Point([-122.34764, 47.61859]), { _timestamp: new Date('Tue, 18 Aug 2020 00:54:53 GMT').getTime() }),
    new atlas.data.Feature(new atlas.data.Point([-122.33787, 47.61295]), { _timestamp: new Date('Tue, 18 Aug 2020 00:56:53 GMT').getTime() }),
    new atlas.data.Feature(new atlas.data.Point([-122.34217, 47.60964]), { _timestamp: new Date('Tue, 18 Aug 2020 00:59:53 GMT').getTime() })
  ];

  constructor() { }

  ngOnInit() {
    this.initializeMap();
  }

  initializeMap() {
    this.map = new atlas.Map(this.myMap.nativeElement, {
      center: [-122.345, 47.615],
      zoom: 14,
      view: 'Auto',
      authOptions: {
        authType: atlas.AuthenticationType.subscriptionKey,
        subscriptionKey: 'API_KEY',
      },
    });

    this.map.events.add('ready', () => this.onMapReady());
  }

  onMapReady() {
    this.map.imageSprite.createFromTemplate('arrow-icon', 'marker-arrow', 'teal', '#fff').then(() => {
      this.initializeSourcesAndLayers();
      this.initializePin();
      this.initializeAnimation();
    });
  }

  initializeSourcesAndLayers() {
    this.lineSource = new atlas.source.DataSource();
    this.pinSource = new atlas.source.DataSource();
    this.map.sources.add([this.lineSource, this.pinSource]);

    const path = this.routePoints.map(f => f.geometry.coordinates);
    this.lineSource.add(new atlas.data.LineString(path));

    this.map.layers.add(new atlas.layer.LineLayer(this.lineSource, null, {
      strokeColor: 'DodgerBlue',
      strokeWidth: 3
    }));

    this.map.layers.add(new atlas.layer.SymbolLayer(this.pinSource, null, {
      iconOptions: {
        image: 'arrow-icon',
        anchor: 'center',
        rotation: ['+', 180, ['get', 'heading']],
        rotationAlignment: 'map',
        ignorePlacement: true,
        allowOverlap: true
      },
      textOptions: {
        ignorePlacement: true,
        allowOverlap: true
      }
    }));
  }

  initializePin() {
    this.pin = new atlas.Shape(this.routePoints[0]);
    this.pinSource.add(this.pin);
  }

  initializeAnimation() {
    this.animation = (window as any).atlas.animations.moveAlongRoute(this.routePoints, this.pin, {
      timestampProperty: 'timestamp',
      captureMetadata: true,
      loop: false,
      reverse: false,
      rotationOffset: 0,
      speedMultiplier: 60,
      map: this.map,
      zoom: 15,
      pitch: 45,
      rotate: true
    });
  }

  toggleAnimationOption(option: string, value?: any) {
    const options = this.animation.getOptions();
    this.animation.setOptions({
      [option]: value !== undefined ? value : !options[option]
    });
  }

  play() { this.animation.play(); }
  pause() { this.animation.pause(); }
  stop() { this.animation.stop(); }
  reset() { this.animation.reset(); }

  toggleFollow() { this.toggleAnimationOption('map', this.map); }
  toggleFollowOffset() { this.toggleAnimationOption('rotationOffset', this.animation.getOptions().rotationOffset === 0 ? 90 : 0);}
  toggleLooping() { this.toggleAnimationOption('loop'); }
  toggleReverse() { this.toggleAnimationOption('reverse'); }
}

When playing the animation, the marker should move accordingly, like in the provided official example.

1 Answer 1

0

The issue where the marker is not animating along the path in Azure Maps within your Angular application can be resolved by adding a RoutePathAnimation class that animates a map and/or a shape (such as a point or an HTML marker) along a route path using Azure Maps to your code.

Refer to this link for the RoutePathAnimation code, and convert the above code to Angular.



export interface RoutePathAnimationEvent {
    position?: azmaps.data.Position;
    heading?: number;
    speed?: number;
    timestamp?: number;
}

@Injectable({
  providedIn: 'root'
})
export class RoutePathAnimationService extends MapPathPlayableAnimation {

  private _shape: azmaps.Shape | azmaps.HtmlMarker;
  private _route: azmaps.data.Feature<azmaps.data.Point, any>[];
  private _totalTime: number;
  private _positions: azmaps.data.Position[];
  private _timestamps: number[];
  private _headingInv: number[];    
  private _speedInv: number[];
  private _timeInv: number[];
  private _valueInterps: PointPairValueInterpolation[];

  constructor() {
    super();
  }

  dispose(): void {
    this._route = null;
    this._headingInv = null;
    this._positions = null;
    this._timestamps = null;
    this._timeInv = null;
    this._totalTime = null;
    this._shape = null;

    super.dispose();
  }

  getDuration(): number {
    if(typeof this._totalTime !== 'undefined'){
        return this._totalTime / this._pathOptions.speedMultiplier;
    }

    return super.getDuration();
  }



Output:

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.