Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import {
- Component,
- EventEmitter,
- Input,
- Output,
- OnDestroy,
- OnChanges,
- SimpleChanges,
- OnInit
- } from '@angular/core';
- import { MapService } from 'src/app/core/services/map/map.service';
- import { Location } from 'src/app/core/models/Location';
- import { GeoJson, FeatureCollection } from 'src/app/core/models/mapbox/Map';
- import { Feature } from 'src/app/core/models/mapbox/MapboxReverseGeocodingResponse';
- import { environment } from 'src/environments/environment';
- import { Geolocation } from '@ionic-native/geolocation/ngx';
- import * as mapboxgl from 'mapbox-gl';
- import * as MapboxGeocoder from '@mapbox/mapbox-gl-geocoder';
- import { BikePartyToastrService } from 'src/app/core/services/toastr/toastr.service';
- const mapStyle = 'mapbox://styles/mapbox/outdoors-v9';
- const defaultCoordinates = {
- latitude: 59.3293,
- longitude: 18.0686
- }; // Stockholm coordinates
- // NOTE: For iOS you have to add this configuration to your configuration.xml file
- // <edit-config file="*-Info.plist" mode="merge" target="NSLocationWhenInUseUsageDescription">
- // <string>We use your location for full functionality of certain app features.</string>
- // </edit-config>
- @Component({
- selector: 'app-map',
- templateUrl: './map.component.html',
- styleUrls: ['./map.component.scss']
- })
- export class MapComponent implements OnChanges, OnDestroy {
- @Input() locations: Location[];
- @Input() isReadOnly = false;
- @Input() mapName = 'map';
- @Output() addressEvent = new EventEmitter();
- @Output() totalTripDistanceEvent = new EventEmitter();
- map: mapboxgl.Map;
- markerSource: any;
- routeSource: any;
- constructor(
- private mapService: MapService,
- private geolocation: Geolocation,
- private toastr: BikePartyToastrService
- ) {}
- ngOnChanges(changes: SimpleChanges) {
- this.locations = changes['locations']
- ? changes['locations'].currentValue
- : this.locations;
- this.mapName = changes['mapName']
- ? changes['mapName'].currentValue
- : this.mapName;
- this.isReadOnly = changes['isReadOnly']
- ? changes['isReadOnly'].currentValue
- : this.isReadOnly;
- if (this.locations) {
- this.buildMap(this.locations, this.mapName);
- } else {
- this.geolocation
- .getCurrentPosition()
- .then(position => {
- this.buildMap([position.coords], this.mapName);
- })
- .catch(() => {
- this.buildMap([defaultCoordinates], this.mapName);
- this.toastr.info(
- 'To have a complete experience of the app, please turn on the location.'
- );
- });
- }
- }
- ngOnDestroy() {
- if (this.map) {
- this.map.remove();
- }
- }
- buildMap(locations: Location[], mapName: string) {
- const averageLongitude =
- locations.map(x => +x.longitude).reduce((a, b) => a + b, 0) /
- locations.length;
- const averageLatitude =
- locations.map(x => +x.latitude).reduce((a, b) => a + b, 0) /
- locations.length;
- setTimeout(() => {
- this.map = new mapboxgl.Map({
- container: mapName,
- style: mapStyle,
- zoom: 14,
- center: [averageLongitude, averageLatitude],
- attributionControl: false
- });
- this.map.on('load', event => {
- if (this.locations) {
- this.initMarkers(this.locations);
- }
- if (locations.length > 1) {
- this.initRoute(locations);
- }
- });
- if (!this.isReadOnly) {
- this.initMapControls();
- }
- this.map.resize();
- }, 1); // this is to fix map bug upon initialization
- }
- initMapControls() {
- this.map.addControl(
- new MapboxGeocoder({
- accessToken: environment.mapbox.accessToken,
- mapboxgl: mapboxgl,
- markers: true
- })
- );
- this.map.on('click', event => {
- const lng = event.lngLat.lng;
- const lat = event.lngLat.lat;
- this.addMarker(lng, lat);
- console.log('lng', lng);
- console.log('lat', lat);
- this.mapService
- .getPointOfInterest(event.lngLat.lng, event.lngLat.lat)
- .then(places => {
- const location = this.parseFeatureToLocation(places.features[0]);
- location.latitude = lat;
- location.longitude = lng;
- this.addressEvent.emit(location);
- })
- .catch(() => {});
- });
- }
- initMarkers(locations: Location[]) {
- if (!this.map.getSource('markers')) {
- this.map.addSource('markers', {
- type: 'geojson',
- data: {
- type: 'FeatureCollection',
- features: []
- }
- });
- }
- this.markerSource = this.map.getSource('markers');
- if (locations) {
- const markers = [];
- locations.forEach(location => {
- if (location.latitude) {
- markers.push(
- new GeoJson([location.longitude, location.latitude], 'Point', {
- message: location.definition
- })
- );
- }
- });
- this.markerSource.setData(new FeatureCollection(markers));
- }
- this.map.addLayer({
- id: 'location',
- source: 'markers',
- type: 'symbol',
- layout: {
- 'text-field': '{message}',
- 'text-size': 15,
- 'text-transform': 'uppercase',
- 'icon-image': 'star-15',
- 'text-offset': [0, 1.5]
- },
- paint: {
- 'text-color': 'red',
- 'text-halo-color': '#fff',
- 'text-halo-width': 2
- }
- });
- }
- initRoute(locations: Location[]) {
- if (!this.map.getSource('route')) {
- this.map.addSource('route', {
- type: 'geojson',
- data: {
- type: 'Feature',
- geometry: null
- }
- });
- }
- this.routeSource = this.map.getSource('route');
- const wayPoints = [];
- locations.forEach((location, index) => {
- if (index < locations.length && location.latitude) {
- wayPoints.push(location.longitude + ',' + location.latitude);
- }
- });
- this.mapService
- .getRouteCoordinates(wayPoints.filter(Boolean).join(';'))
- .then(response => {
- this.routeSource.setData({
- type: 'Feature',
- geometry: {
- type: 'LineString',
- coordinates: response.routes[0].geometry.coordinates
- }
- });
- this.totalTripDistanceEvent.emit(response.routes[0].distance);
- });
- if (!this.map.getLayer('routeline-active')) {
- this.map.addLayer(
- {
- id: 'routeline-active',
- type: 'line',
- source: 'route',
- layout: {
- 'line-join': 'round',
- 'line-cap': 'round'
- },
- paint: {
- 'line-color': '#3887be',
- 'line-width': ['interpolate', ['linear'], ['zoom'], 12, 3, 22, 12]
- }
- },
- 'waterway-label'
- );
- }
- }
- addMarker(lng: number, lat: number): void {
- const marker = new GeoJson([lng, lat], 'Point', { message: '' });
- const data = new FeatureCollection([marker]);
- this.markerSource.setData(data);
- }
- parseFeatureToLocation(data: Feature): Location {
- return {
- postalCode: data.context.find(x => x.id.includes('postcode')).text || '',
- street: data.properties.address || '',
- city: data.context.find(x => x.id.includes('place')).text || '',
- country: data.context.find(x => x.id.includes('country')).text || '',
- name: data.text || ''
- };
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement