Forum Discussion

victorguillen's avatar
victorguillen
Copper Contributor
Aug 13, 2024

azure-maps-animations wont animate marker in Angular 17

Hello. I'm trying to replicate this https://samples.azuremaps.com/?sample=animate-along-a-route-path, 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 https://github.com/Azure-Samples/azure-maps-animations/releases/tag/252490. (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'); }
}

 

1 Reply

Resources