Coder Social home page Coder Social logo

Custom Map Marker about vue-azure-maps HOT 4 CLOSED

rickyruiz avatar rickyruiz commented on September 15, 2024
Custom Map Marker

from vue-azure-maps.

Comments (4)

jawa-the-hutt avatar jawa-the-hutt commented on September 15, 2024

Here's a basic example of what I'm using on this. I adapted it from the AzureMapExamples.vue file included in the demo.

Here's how it looks at the moment:
image

There ends up being a console error:
image

here's the basic logic:

<template>
  <AzureMap ref="map"
    :center="mapOptions.center"
    class="AzureMap"
    @mousemove="onMouseMove"
    @mouseup="onMouseUp"
    :zoom="6"
    mapStyle="night"
    
  >
    <!-- Azure Map controls -->
    <AzureMapZoomControl />
    <AzureMapPitchControl />
    <AzureMapCompassControl />
    <AzureMapFullscreenControl />

    <!-- Create a Data Source -->
    <AzureMapDataSource>
      <!-- Add a Symbol Layer to render the Points stored in the Data Source -->
      <AzureMapSymbolLayer
        :options="symbolLayerOptions"
        @mouseenter="onMouseEnter"
        @mouseleave="onMouseLeave"
        @mousedown="onMouseDown"
      />
      <!-- <AzureMapSymbolLayer :options="symbolLayerOptions" /> -->
      <template v-for="flight in flights">
        <!-- Add Points to the Data Source -->
        <AzureMapPoint :key="flight.properties.name" :longitude="flight.longitude" :latitude="flight.latitude" :properties="flight.properties" />
        <!-- Add a Popup to the map for every Point -->
        <AzureMapPopup
          :key="`Popup-${flight.properties.name}`"
          v-model="flight.properties.isPopupOpen"
          :position="[flight.longitude, flight.latitude]"
          :pixel-offset="[0, -18]"
          :close-button="false"
          class="AzureMapPopup"
        >
          <p>
            <strong>Name: {{ flight.properties.name }}</strong>
          </p>
          <p>Altitude: {{ flight.properties.altitude }}</p>
          <p>Rotation: {{ flight.properties.rotation }}</p>
        </AzureMapPopup>
      </template>
    </AzureMapDataSource>
  </AzureMap>
</template>

<script lang="ts">
import {
  AzureMap,
  AzureMapDataSource,
  AzureMapPopup,
  AzureMapPoint,
  AzureMapZoomControl,
  AzureMapPitchControl,
  AzureMapCompassControl,
  AzureMapFullscreenControl,
  AzureMapSymbolLayer,
} from 'vue-azure-maps';

import atlas from 'azure-maps-control';
import Vue from 'vue';

type MapOptions = atlas.ServiceOptions &
  atlas.CameraOptions &
  atlas.UserInteractionOptions;

type CustomPoint = {
  longitude: number;
  latitude: number;
  properties: Record<string, any>;
};

export default Vue.extend({
  name: 'AzureMapExample',

  components: {
    AzureMap,
    AzureMapDataSource,
    AzureMapPopup,
    AzureMapPoint,
    AzureMapZoomControl,
    AzureMapPitchControl,
    AzureMapCompassControl,
    AzureMapFullscreenControl,
    AzureMapSymbolLayer
  },

  data() {
    return {
      map: {} as atlas.Map,
      flights: [] as CustomPoint[],

      mapOptions: {
        center: [171.7799, -40.838875]
      } as MapOptions,

      symbolLayerOptions: {
        iconOptions: {
          ignorePlacement: true,
          allowOverlap: true,
          image: 'pin-red',   //  <-- This should be 'plane-icon' but won't load the sprite
          size: 0.75,
          rotation: ['get', 'rotation']
        },
        textOptions: {
          textField: ['concat', ['to-string', ['get', 'name']], '- ', ['get', 'altitude']],
          color: '#FFFFFF',
          offset: [2, 0]
        }
      } as atlas.SymbolLayerOptions,

      selectedShape: null as atlas.Shape | null,
      selectedFlight: null as CustomPoint | null
    };
  },

  mounted() {
    this.axios.get('https://opensky-network.org/api/states/all?lamin=-50.00&lomin=160.00&lamax=-30.00&lomax=180.00').then((response) => {
      // console.log(response.data);

      for (const flight of response.data.states) {
        // console.log('flight - ', flight);
        let f: CustomPoint = {
          longitude: parseFloat(flight[5]),
          latitude: parseFloat(flight[6]),
          properties: {
            name: flight[1],
            altitude: flight[7],
            rotation: flight[10],
            isPopupOpen: false
          }
        };
        this.flights.push(f);
      }
    });

    // @ts-ignore
    this.map = this.$refs.map.getMap();
    this.addSprite('plane-icon', '../assets/plane.png');
  },

  methods: {
    addSprite(type: string, address: string) {
      // @ts-ignore
      this.map.imageSprite.add(type, address);
    },
    getCustomFlightByName(name: string): CustomPoint | undefined {
      return this.flights.find(p => p.properties.name === name);
    },
    onMouseEnter(e: atlas.MapMouseEvent): void {
      if (e.shapes && e.shapes.length > 0) {
        // Capture the selected shape.
        const selectedShape = e.shapes[0] as atlas.Shape;

        // Check if the flight is in our data
        let flight = this.getCustomFlightByName(
          selectedShape.getProperties().name
        );

        if (flight) {
          // Capture the selected flight.
          this.selectedFlight = flight;

          // Show the popup
          flight.properties.isPopupOpen = true;
        }
      }
    },
    onMouseLeave(e: atlas.MapMouseEvent): void {
      // Hide the popup
      if (this.selectedFlight) {
        this.selectedFlight.properties.isPopupOpen = false;

        // Stop tracking the selected flight.
        this.selectedFlight = null;
      }
    },
    onMouseDown(e: atlas.MapMouseEvent): void {
      if (e.shapes && e.shapes.length > 0) {
        // Capture the selected shape.
        this.selectedShape = e.shapes[0] as atlas.Shape;
        // Lock the maps ability to pan so that we can drag the symbol.
        e.map.setUserInteraction({
          dragPanInteraction: false
        });
      }
    },
    onMouseMove(e: atlas.MapMouseEvent): void {
      // Update the position of the selected shape.
      if (this.selectedShape && e.position) {
        // Check if the flight is in our data
        let flight = this.getCustomFlightByName(
          this.selectedShape.getProperties().name
        );

        if (flight) {
          // Update the longitude and latitude
          [flight.longitude, flight.latitude] = e.position;
        }
      }
    },
    onMouseUp(e: atlas.MapMouseEvent): void {
      // Stop tracking the selected shape.
      this.selectedShape = null;
      // Make map panable again.
      e.map.setUserInteraction({
        dragPanInteraction: true
      });
    }
  }
});
</script>

<style scoped>
.AzureMap {
  width: 100%;
  height: 100%;
}

.AzureMapPopup {
  max-width: 200px;
  padding: 1rem;
}
</style>

from vue-azure-maps.

rickyruiz avatar rickyruiz commented on September 15, 2024

Yes there is! When the map resources are ready, the AzureMap component emits the ready event from which you can get the map instance. Instead of using ref do the following:

<AzureMap
  @ready="onMapReady"  
/>
methods: {
  onMapReady(e: atlas.MapEvent): void {
    this.map = e.map
    this.map.imageSprite.add('plane-icon', '/plane.png')
  }.
},

The atlas.MapEvent interface:

  /**
    * Event object returned by the maps when a basic event occurs.
    */
   export interface MapEvent {
       /**
        * The original event that was fired.
        */
       originalEvent?: Event;
       /**
        * The `Map` instance in which the event occurred on.
        */
       map: atlas.Map;
       /**
        * The event type.
        */
       type: string;
   }

The imageSprite.add method returns a promise, I believe the example creates the data source after the promise resolves since it is loading the image from an external source. You could do the same by using a boolean flag: <AzureMapDataSource v-if="isPlaneIconReady"/>

Here's a working example:
https://codesandbox.io/s/vue-azure-map-image-sprite-9e0vm

from vue-azure-maps.

jawa-the-hutt avatar jawa-the-hutt commented on September 15, 2024

Awesome...that works. Thanks for the help.

from vue-azure-maps.

rickyruiz avatar rickyruiz commented on September 15, 2024

@jawa-the-hutt I created a new component so that it is easier to add icons to the map's image sprite.

You'll be able to add it like so:

<!-- Add an icon to the map's image sprite -->
<AzureMapImageSpriteIcon
  id="vue-azure-maps-logo"
  :icon="require('@/assets/logo.png')"
  @added="isCustomIconAdded = true"
  @removed="..."
  @error="..."
/>
customIconSymbolLayerOptions: {
  iconOptions: {
    image: 'vue-azure-maps-logo',
    size: 0.1,
  },
} as atlas.SymbolLayerOptions,

Props:

  props: {
    /**
     * The image's id.
     */
    id: {
      type: String,
      default: null,
      required: true,
    },

    /**
     * The image to add to the map's sprite. Can be a data URI, inline SVG, or image URL.
     */
    icon: {
      type: [String, Object] as PropType<string | HTMLImageElement | ImageData>,
      default: null,
      required: true,
    },
  },

Events:

enum AzureMapImageSpriteIconEvent {
  Error = 'error',
  Added = 'added',
  Removed = 'removed',
}

This is now available in version 0.0.20.

from vue-azure-maps.

Related Issues (13)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.