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.
front/src/app/components/leaflet-map/leaflet-map.component.ts

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],
});
}
}