leaflet to geoJSON with angular, download not triggered - javascript

I need to implement a button that download the polygon (or whatever shape) into a geojson file but the download isn't triggered. (trying with 2 different functions but both not working) i actually don't know if i got the functions wrong/missing something or the problem is in the .html
app.component.ts
import { Component } from '#angular/core';
import { latLng, tileLayer, DrawOptions, DrawEvents } from 'leaflet';
import { icon, marker, polyline, circle, rectangle, polygon} from 'leaflet';
import { LeafletModule } from '#asymmetrik/ngx-leaflet';
import { LeafletDrawModule } from '#asymmetrik/ngx-leaflet-draw';
import { DomSanitizer, SafeUrl, SafeResourceUrl } from '#angular/platform-browser';
import { FeatureGroup, featureGroup } from 'leaflet';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'tesiangularp';
options = {
layers: [
tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
})
],
zoom: 7,
center: latLng([ 41.471276, 12.907632 ])
};
layersControl = {
baseLayers: {
'Open Street Map': tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18, attribution: '...' }),
'Satellite View Map': tileLayer('http://{s}.google.com/vt/lyrs=s&x={x}&y={y}&z={z}', {
maxZoom: 18, attribution: '...', subdomains:['mt0','mt1','mt2','mt3']})
},
overlays: {
}
}
drawnItems: FeatureGroup = featureGroup();
drawOptions = {
edit: {
featureGroup: this.drawnItems
},
Draw: {
}
};
public onDrawCreated(e: any) {
this.drawnItems.addLayer((e as DrawEvents.Created).layer);
}
geoExport =() => {
let nodata = '{"type":"FeatureCollection","features":[]}';
let jsonData = (JSON.stringify(this.drawnItems.toGeoJSON()));
let dataUri = 'data:application/json;charset=utf-8,'+ encodeURIComponent(jsonData);
let datenow = new Date();
let datenowstr = datenow.toLocaleDateString('en-GB');
let exportFileDefaultName = 'export_draw_'+ datenowstr + '.geojson';
let linkElement = document.createElement('a');
linkElement.setAttribute('href', dataUri);
linkElement.setAttribute('download', exportFileDefaultName);
if (jsonData == nodata) {
alert('No features are drawn');
} else {
linkElement.click();
}
}
exportJson() {
var data = this.drawnItems.toGeoJSON();
var convertedData = 'text/json;charset=UTF-8,' + encodeURIComponent(JSON.stringify(data));
document.getElementById('export')?.setAttribute('href', 'data:' + convertedData);
document.getElementById('export')?.setAttribute('download', 'data.json');
}
}
app.component.html
<div class="map"
leaflet
leafletDraw
[leafletOptions]="options"
[leafletLayersControl]="layersControl"
[leafletDrawOptions]="drawOptions"
(leafletDrawCreated)="onDrawCreated($event)">
<div [leafletLayer]="drawnItems"></div>
</div>
<a>
<div style="margin: 2px 0px 2px 0px;">
<button onclick= "exportJson()">Download</button>
</div>
</a>

There are differences in how browsers handle client side file creation. So, I would use a library called file-saver.
npm install file-saver
Then import it into the component
import { saveAs } from 'file-saver';
And save your geojson
const geojson = this.drawnItems.toGeoJSON();
const blob = new Blob([geojson], {type: 'application/json;charset=utf-8'});
saveAs(blob, 'drawnItems.geojson');

Related

Leaflet marker not appearing when using observables

map.component.ts
export class MapComponent implements AfterViewInit {
private map;
private centroid: L.LatLngExpression = [49.2827, -123.1207];
private initMap(): void {
this.map = L.map('map', {
center: this.centroid,
zoom: 12
});
const tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
minZoom: 3,
attribution: '© OpenStreetMap'
});
tiles.addTo(this.map);
}
constructor(private _dataService: DataService) {
}
ngAfterViewInit(): void {
this.initMap();
this._dataService.pigMessage$.subscribe(message => {
L.marker([49.2827, -123.1207]).addTo(this.map).bindPopup("test").openPopup();
console.log(message);
})
}
}
data.service.ts
import { Injectable } from '#angular/core';
import { Subject } from 'rxjs';
import { pigReportType } from './pigReport';
#Injectable({
providedIn: 'root'
})
export class DataService {
private _pigMessageSource = new Subject<pigReportType>();
pigMessage$ = this._pigMessageSource.asObservable();
sendPigData(message: pigReportType){
this._pigMessageSource.next(message)
}
constructor() { }
}
When I click on the submit button, data service sends a new piece of information into the observable and redirects back to the map component. The problem is the marker is not adding inside of the subscribe function in map.component.ts.
Additionally, I have checked that the .subscribe function works because it prints the correct message. The markers just do not appear on the map.
I have tried looking through the html and seeing if there is a duplicated map that is covering the map with the marker but there isn't. Also I have tried to call initMap inside of the .subscribe function but it doesn't work.
I'm hoping if someone can point me in the right direction because I have searched everywhere on the web for a solution but can't find it.

leaflet replay on map plot replay history of vehicle

my question is how to replay the hisotory of vehicle on leaflet map i have plot the polyline on map but maker is not poloting the marker should plot according to start and stop button i have done this code give me suggesstion how to add anymation marker on map the marker paly using button and stop also using button
import { Component, ElementRef, NgZone, OnInit, ViewChild } from '#angular/core';
import { FormBuilder, FormGroup } from '#angular/forms';
import * as moment from 'moment';
import { interval, Subject, PartialObserver, Observable, Subscriber, of, timer, Subscription } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { ReplayService } from 'src/app/Core/services/monitoring/replay.service';
import * as L from 'leaflet';
import 'leaflet.animatedmarker/src/AnimatedMarker'
import * as $ from 'jquery';
import { waitForAsync } from '#angular/core/testing';
#Component({
selector: 'app-replay',
templateUrl: './replay.component.html',
styleUrls: ['./replay.component.css'],
})
export class ReplayComponent implements OnInit {
displayedColumns: any[] = ['startDateTime', 'endDateTime', 'vehicleRegNo'];
newArr: any[] = [];
arrayofLatLng = [];
replayFrom: FormGroup;
map: L.Map;
private centroid: L.LatLngExpression = [13.30153, 79.93975];//13.30153/79.93975
ployLine: any;
route: any;
replayData: any[] = [];
replayRow: any;
nowTabelData:any[]=[];
animatedMarker;
myIcon=L.icon({
iconUrl: '/assets/images/truck.png',
iconSize: [32, 37],
iconAnchor: [16, 37],
popupAnchor: [0, -28]
});
constructor(private formBuilder: FormBuilder, private replayService: ReplayService) {
this.replayFrom = this.formBuilder.group({
startDateTime: ['', ''],
endDateTime: ['', ''],
vehicleRegNo: ['', ''],
})
}
getData(replayFrom: FormGroup) {
console.log(this.replayFrom.value);
let startDateTime = replayFrom.value.startDateTime;
let endDateTime = replayFrom.value.endDateTime;
let vehicleRegNo = replayFrom.value.vehicleRegNo;
let abc = replayFrom.value;
let fromDateFormat = moment(new Date(startDateTime)).format("YYYY-MM-DD HH:mm:ss");
let toDateFormat = moment(new Date(endDateTime)).format("YYYY-MM-DD HH:mm:ss");
this.getReplayData(fromDateFormat, toDateFormat, vehicleRegNo, abc);
}
ngOnInit() {
}
sub: Subscription;
getReplayData(startDateTime: string, endDateTime: string, vehicleRegNo: string, abc: any) {
this.replayService.getReplay(startDateTime, endDateTime, vehicleRegNo, abc)
.subscribe({
next: this.handleReplayResponse.bind(this),
error: this.handleReplayError.bind(this),
});
}
handleReplayResponse(res: any): void {
let tempArr = res.data;
this.replayData = tempArr;
this.myLoop();
}
i=0;
j=10;
k=0;
t=0;
myLoop(){
let letLng=[] ;
setTimeout(()=> {
this.i++;
console.log(this.i);
if (this.i < this.replayData.length) {
console.log(this.replayData.length);
this.myLoop();
console.log(this.replayData[this.i].eventLat);
for(;this.k<this.j;this.k++){
console.log(this.k);
this.nowTabelData.push(this.replayData[this.k]);
const latN = this.replayData[this.k].eventLat;
const lanN = this.replayData[this.k].eventLong;
if (latN > 0 && lanN > 0 && latN!=undefined && lanN!=undefined) {
this.arrayofLatLng.push([latN, lanN]);
letLng.push([latN,lanN]);
}
}
this.i=this.k;
this.k=this.j;
this.j=this.j+10;
}
debugger;
console.log(letLng);
console.log(this.arrayofLatLng);
this.ployLine = new L.Polyline([this.arrayofLatLng], {
weight: 8,
color: 'red'
}).addTo(this.map);
this.animatedMarker=L.animatedMarker(this.arrayofLatLng,{icon:this.myIcon,interval:100,autoStart:false});
this.map.addLayer(this.animatedMarker);
}, 1000);
}
startMarker(){
this.t=0;
this.animatedMarker.start();
}
handleReplayError(err: any) {
console.log(err);
}
private initMap(): void {
this.map = L.map('map', {
center: this.centroid,
zoom: 10
});
const tiles = L.tileLayer('http://3.110.6.95:8070/mapcache/tms/1.0.0/osmindiamap#indiagrid/{z}/{x}/{-y}.png', {
maxZoom: 18,
minZoom: 2,
attribution: '© OpenStreetMap'
})
tiles.addTo(this.map);
}
ngAfterViewInit() {
this.initMap();
}
pauseMarker(){
this.t=1;
this.animatedMarker.stop();
}
}

Click on zoom button trigger go thought all div and trigger my map function Anuglar10 / OpenLayer6

I have an issue using event with OpenLayers and Angular, I have an function on click on my map which catch me the lonlat from where I have clicked on the map but, when I click on the zoom in and out control the function is also triggered same thing when I drag my view which I don't what to happen. It's the first time i'm using this API, can someone help me ?
my TS file
import { Component, OnInit } from '#angular/core';
import Map from 'ol/Map';
import Tile from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
import View from 'ol/View';
import { fromLonLat, transform } from 'ol/proj';
import VectorSource from 'ol/source/Vector';
import VectorLayer from 'ol/layer/Vector';
import { Feature } from 'ol';
import Point from 'ol/geom/Point';
import Style from 'ol/style/Style';
import Icon from 'ol/style/Icon'
#Component({
selector: 'app-indicator-acceuil',
templateUrl: './indicator-acceuil.component.html',
styleUrls: ['./indicator-acceuil.component.scss']
})
export class IndicatorAcceuilComponent implements OnInit {
map: any;
markerSource: VectorSource = new VectorSource({});
constructor() { }
ngOnInit(): void {
this.initilizeMap();
}
initilizeMap() {
this.map = new Map({
target: 'map',
layers: [
new Tile({
source: new OSM()
}),
new VectorLayer({
source: this.markerSource,
style: new Style({
image: new Icon({
anchor : [0.5,1],
src: 'assets/pin24x24.png',
scale : 1.5,
imgSize: [24,24],
})
})
})
],
view: new View({
center: fromLonLat([2.213749,46.227638]),
zoom: 6
}),
});
}
getCoord(event: any) {
const coordinate = this.map.getEventCoordinate(event);
let lonlat = transform(coordinate, 'EPSG:3857', 'EPSG:4326');
const lon = lonlat[0];
const lat = lonlat[1];
console.log(lonlat)
this.addMarker(lon, lat);
}
addMarker(lon: number, lat: number) {
this.markerSource.clear();
let marker = new Feature({
geometry: new Point(fromLonLat([lon,lat])) // dont worry about coordinate type 0,0 will be in west coast of africa
});
this.markerSource.addFeature(marker)
}
}
My html file
<div id="map" (click)="getCoord($event)"></div>

Leaflet - import Geojson - Angular 6

i try to import GeoJson file to leaflet in angular's app 6.
With this solution my geojson is drawn in leafletmap but i have this error and i can't build my app. Someone know one solution ?
ERROR TS2345 Argument of type '{"type": string;"features":({"type":
string; "geometry": { "type: string : "coordinates": num...' is not
assignable parameter of type GeoJsonObject
Model.ts
export const Pdl = [ 'my geojson' ];
https://raw.githubusercontent.com/alanent/france-geojson/master/regions/pays-de-la-loire/departements-pays-de-la-loire.geojson
Component.ts
import { LeafletModule } from '#asymmetrik/ngx-leaflet';
import * as L from 'leaflet';
import {Pdl} from "../models/pdl.model";
#Component({
selector: 'app-geo',
templateUrl: './geo.component.html',
styleUrls: ['./geo.component.scss']
})
export class GeoComponent implements OnInit {
ngOnInit() {
var mapboxAccessToken = "...";
const myfrugalmap = L.map('frugalmap').setView([47.482019, -1], 7);
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=' + mapboxAccessToken, {
id: 'mapbox.light',
attribution: 'SOS'
}).addTo(myfrugalmap);
L.geoJSON(Pdl).addTo(myfrugalmap);
}
}
Maybe, i can hide the error ? what is the way ?
You need to do it the 'angular way' since you are using ngx-leaflet
Importing a json via import is a nightmare in my personal opinion so what I would do would be to fetch it using a get request when the map is loaded and then get a reference to the map object and add the geojson.
template:
import { HttpClient } from '#angular/common/http';
import * as L from 'leaflet';
..
map: L.Map;
json;
options = {
layers: [
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18, attribution: '...'
})
],
zoom: 7,
center: L.latLng(47.482019, -1)
};
constructor(private http: HttpClient) { }
onMapReady(map: L.Map) {
this.http.get('assets/departements.json').subscribe((json: any) => {
console.log(json);
this.json = json;
L.geoJSON(this.json).addTo(map);
});
}
template
<div leaflet style="height: 800px"
[leafletOptions]="options"
(leafletMapReady)="onMapReady($event)">
</div>
Demo

Fix scopes in Angular component

I'm using 2GIS maps API based on Leaflet library. There are few functions in MapService (such as addMarkerToList()) which need to be called while clicking on map.
But there is a problem: using this.mapService.addMarkerToList will caught an error:
ERROR TypeError: Cannot read property 'addMarkerToList' of undefined
So I use const self = this construction to avoid this problem.
Can it be solved by another way?
map.component.ts
import {Component, OnInit} from '#angular/core';
import * as DG from '2gis-maps';
import {MapService} from '../../services/map/map.service';
let currentUserPos;
#Component({
selector: 'app-map',
templateUrl: './map.component.html',
styleUrls: ['./map.component.css']
})
export class MapComponent implements OnInit {
constructor(private mapService: MapService) {}
ngOnInit() {
const self = this;
const map = DG.map('map', {
'center': [54.98, 82.89],
'zoom': 13,
'fullscreenControl': false
});
if (map) {
console.log('Map added');
}
map.locate()
.on('locationfound', function (e) {
currentUserPos = DG.marker([e.latitude, e.longitude]).addTo(map).bindLabel('Your location', {
static: true
});
const currentCenter = new DG.latLng(e.latitude, e.longitude);
console.log('Current position founded: ' + 'lat = ' + e.latitude + '; lng = ' + e.longitude);
map.setView(currentCenter, 16);
});
map.on('click', function (e) {
const marker = DG.marker([e.latlng.lat, e.latlng.lng]);
marker.addTo(map);
marker.on('click', function() {
marker.remove(map);
self.mapService.deleteMarkerFromList(e.latlng.lat, e.latlng.lng);
});
console.log('Marker after adding:' + marker.getLatLng());
self.mapService.addMarkerToList(e.latlng.lat, e.latlng.lng);
});
}
}

Categories