You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
89 lines
3.4 KiB
89 lines
3.4 KiB
import { Component, OnInit, ViewContainerRef } from '@angular/core';
|
|
import * as L from 'leaflet';
|
|
import 'leaflet/dist/leaflet.css';
|
|
import { Monument } from '../../model/Monument';
|
|
import { PinService } from '../../services/pin.service';
|
|
import { MonumentMarkerComponent } from '../monument-marker/monument-marker.component';
|
|
|
|
@Component({
|
|
selector: 'app-leaflet-map',
|
|
templateUrl: './leaflet-map.component.html',
|
|
})
|
|
export class LeafletMapComponent implements OnInit {
|
|
private map!: L.Map;
|
|
|
|
constructor(
|
|
private viewContainerRef: ViewContainerRef,
|
|
private pinsService: PinService
|
|
) {}
|
|
|
|
ngOnInit(): void {
|
|
this.initializeMap();
|
|
}
|
|
|
|
private initializeMap(): void {
|
|
// Initialize the map
|
|
this.map = L.map('map', {
|
|
maxBounds: L.latLngBounds(
|
|
L.latLng(-90, -180), // South-West
|
|
L.latLng(90, 180) // North-East
|
|
),
|
|
maxBoundsViscosity: 1.0, // Prevent dragging the map out of bounds
|
|
minZoom: 2, // Prevent zooming out too much
|
|
}).setView([46.603354, 1.888334], 6);
|
|
|
|
// Add OpenStreetMap tiles
|
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
|
attribution: '',
|
|
}).addTo(this.map);
|
|
this.map.attributionControl.setPrefix('');
|
|
|
|
// Define custom icons
|
|
const visitedIcon = this.createDivIcon(`
|
|
<svg class="w-6 h-6 text-gray-800" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 24 24">
|
|
<path fill-rule="evenodd" d="M11.906 1.994a8.002 8.002 0 0 1 8.09 8.421 7.996 7.996 0 0 1-1.297 3.957.996.996 0 0 1-.133.204l-.108.129c-.178.243-.37.477-.573.699l-5.112 6.224a1 1 0 0 1-1.545 0L5.982 15.26l-.002-.002a18.146 18.146 0 0 1-.309-.38l-.133-.163a.999.999 0 0 1-.13-.202 7.995 7.995 0 0 1 6.498-12.518ZM15 9.997a3 3 0 1 1-5.999 0 3 3 0 0 1 5.999 0Z" clip-rule="evenodd"/>
|
|
</svg>
|
|
`);
|
|
|
|
const notVisitedIcon = this.createDivIcon(`
|
|
<svg class="w-6 h-6 text-gray-800" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
<path stroke="currentColor" stroke-width="3" d="M11.083 5.104c.35-.8 1.485-.8 1.834 0l1.752 4.022a1 1 0 0 0 .84.597l4.463.342c.9.069 1.255 1.2.556 1.771l-3.33 2.723a1 1 0 0 0-.337 1.016l1.03 4.119c.214.858-.71 1.552-1.474 1.106l-3.913-2.281a1 1 0 0 0-1.008 0L7.583 20.8c-.764.446-1.688-.248-1.474-1.106l1.03-4.119A1 1 0 0 0 6.8 14.56l-3.33-2.723c-.698-.571-.342-1.702.557-1.771l4.462-.342a1 1 0 0 0 .84-.597l1.753-4.022Z"/>
|
|
</svg>
|
|
`);
|
|
|
|
this.pinsService.getPins().subscribe((monuments: Monument[]) => {
|
|
console.log(monuments);
|
|
// Add markers
|
|
monuments.forEach((monument: Monument) => {
|
|
//const icon = monument.visited ? visitedIcon : notVisitedIcon;
|
|
const icon = visitedIcon;
|
|
|
|
const marker = L.marker(monument.location as [number, number], {
|
|
icon,
|
|
}).addTo(this.map);
|
|
|
|
// Dynamically create Angular component and attach it to popup
|
|
const popupDiv = document.createElement('div');
|
|
const componentRef = this.viewContainerRef.createComponent(
|
|
MonumentMarkerComponent
|
|
);
|
|
|
|
componentRef.instance.monument = monument;
|
|
popupDiv.appendChild(componentRef.location.nativeElement);
|
|
|
|
marker.bindPopup(popupDiv);
|
|
});
|
|
});
|
|
}
|
|
|
|
private createDivIcon(htmlContent: string): L.DivIcon {
|
|
return L.divIcon({
|
|
html: htmlContent,
|
|
className: 'text-2xl text-blue-500',
|
|
iconSize: [24, 24],
|
|
iconAnchor: [12, 24],
|
|
popupAnchor: [0, -24],
|
|
});
|
|
}
|
|
}
|