Skip to content

Commit

Permalink
Merge pull request #91 from Sybit-Education/feat/map-icons
Browse files Browse the repository at this point in the history
Feat/map icons
  • Loading branch information
AlexanderKugler authored Aug 2, 2024
2 parents b10a495 + b9e5b1f commit 3f1e8ff
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 122 deletions.
243 changes: 123 additions & 120 deletions src/app/components/map/map.component.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {Map, MapBrowserEvent, View} from 'ol';
import {Map, View} from 'ol';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer';
import {OSM, Vector as VectorSource} from 'ol/source';
import Feature from 'ol/Feature';
import {Geometry, Point} from 'ol/geom';
import {Circle, Fill, Stroke, Style} from 'ol/style';
import {fromLonLat} from 'ol/proj';
import {Router} from '@angular/router';
import {AirtableService} from '../../services/airtable.service';
import {NgStyle} from "@angular/common";
import { Point, Geometry } from 'ol/geom';
import { Style, Icon } from 'ol/style';
import { fromLonLat } from 'ol/proj';
import { Router } from '@angular/router';
import { AirtableService } from '../../services/airtable.service';
import { MapBrowserEvent } from 'ol';
import { NgStyle } from "@angular/common";

@Component({
selector: 'app-map',
Expand All @@ -20,126 +21,128 @@ import {NgStyle} from "@angular/common";
styleUrls: ['./map.component.scss']
})
export class MapComponent implements OnInit {
map!: Map;
vectorSource!: VectorSource;
map!: Map;
vectorSource!: VectorSource;

@ViewChild('tooltip_map', {static: true}) tooltip!: ElementRef;

constructor(private router: Router, private airtableService: AirtableService) {
}

getBookmarked(osm_id: number | null | undefined) {
const item = localStorage.getItem("savedLocations")
if (item) {
const savedLocations = JSON.parse(item)
return savedLocations.includes(osm_id)
}
}

ngOnInit(): void {
this.vectorSource = new VectorSource();
const vectorLayer = new VectorLayer({
source: this.vectorSource
});

this.map = new Map({
target: 'map',
layers: [
new TileLayer({
source: new OSM()
}),
vectorLayer
],
view: new View({
center: fromLonLat([8.970869314606485, 47.73981783654207]),
zoom: 3,
minZoom: 12,
maxZoom: 25
})
});

this.map.on('click', this.handleMapClick.bind(this));
this.map.on('pointermove', this.handlePointerMove.bind(this));

this.airtableService.getActivityList().subscribe(activities => {
activities.forEach(activity => {
const feature = new Feature({
geometry: new Point(fromLonLat([activity.longitude, activity.latitude])),
activity: activity
});
iconSize = 0.15;

const local = this.getBookmarked(activity.osm_id);
const borderSize = local ? 10.0 : 0.75
const color = local ? "gold" : "black"

feature.setStyle(new Style({
image: new Circle({
radius: 8,
fill: new Fill({color: activity.type.color}),
stroke: new Stroke({color: color, width: borderSize})
})
}));

this.vectorSource.addFeature(feature);
});
});

}
@ViewChild('tooltip_map', {static: true}) tooltip!: ElementRef;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
handleMapClick(event: MapBrowserEvent<any>) {
this.map.forEachFeatureAtPixel(event.pixel, (feature) => {
const activity = (feature as Feature<Geometry>).get('activity');
if (activity) {
this.openDetailPage(activity.osm_id);
}
});
constructor(private router: Router, private airtableService: AirtableService) {}

getBookmarked(osm_id: number | null | undefined) {
const item = localStorage.getItem("savedLocations")
if (item) {
const savedLocations = JSON.parse(item)
return savedLocations.includes(osm_id)
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
handlePointerMove(event: MapBrowserEvent<any>) {
const pixel = this.map.getEventPixel(event.originalEvent);
let featureFound = false;

this.map.forEachFeatureAtPixel(pixel, (feature) => {
featureFound = true;
const activity = (feature as Feature<Geometry>).get('activity');
if (activity) {
const tooltipElement = this.tooltip.nativeElement;
const borderSize = this.getBookmarked(activity.osm_id) ? 5.0 : 0.75
const color = this.getBookmarked(activity.osm_id) ? "gold" : "black"
tooltipElement.innerHTML = activity.name + ' (' + activity.type.name + (this.getBookmarked(activity.osm_id) ? " / favorisiert" : "") + ')';
tooltipElement.style.display = 'block';
tooltipElement.style.left = event.originalEvent.pageX + 'px';
tooltipElement.style.top = (event.originalEvent.pageY - 15) + 'px';
(feature as Feature<Geometry>).setStyle(new Style({
image: new Circle({
radius: 10,
fill: new Fill({color: activity.type.color}),
stroke: new Stroke({color: color, width: borderSize})
})
}));
}
return false;
}

ngOnInit(): void {
this.vectorSource = new VectorSource();
const vectorLayer = new VectorLayer({
source: this.vectorSource
});

this.map = new Map({
target: 'map',
layers: [
new TileLayer({
source: new OSM()
}),
vectorLayer
],
view: new View({
center: fromLonLat([8.970869314606485, 47.73981783654207]),
zoom: 3,
minZoom: 10,
maxZoom: 25
})
});

this.map.on('click', this.handleMapClick.bind(this));
this.map.on('pointermove', this.handlePointerMove.bind(this));

// INITIALIZE

this.airtableService.getActivityList().subscribe(activities => {
activities.forEach(activity => {
const local = this.getBookmarked(activity.osm_id);
console.log(`Activity: ${activity.name}, Bookmarked: ${local}, Color: ${activity.type.color}`);

const feature = new Feature({
geometry: new Point(fromLonLat([activity.longitude, activity.latitude])),
activity: activity
});

if (!featureFound) {
this.tooltip.nativeElement.style.display = 'none';
this.vectorSource.getFeatures().forEach((feature: Feature<Geometry>) => {
const activity = feature.get('activity');
const borderSize = this.getBookmarked(activity.osm_id) ? 5.0 : 0.75
const color = this.getBookmarked(activity.osm_id) ? "gold" : "black"
feature.setStyle(new Style({
image: new Circle({
radius: 8,
fill: new Fill({color: activity.type.color}),
stroke: new Stroke({color: color, width: borderSize})
})
}));
});
}

feature.setStyle(new Style({
image: new Icon({
src: 'data:image/svg+xml;utf8,' + activity.type.svg,
color: activity.type.color,
size: [this.iconSize, this.iconSize]
})
}));

this.vectorSource.addFeature(feature);
});
});
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
handleMapClick(event: MapBrowserEvent<any>) {
this.map.forEachFeatureAtPixel(event.pixel, (feature) => {
const activity = (feature as Feature<Geometry>).get('activity');
if (activity) {
this.openDetailPage(activity.osm_id);
}
});
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
handlePointerMove(event: MapBrowserEvent<any>) {
const pixel = this.map.getEventPixel(event.originalEvent);
let featureFound = false;

// HOVER

this.map.forEachFeatureAtPixel(pixel, (feature) => {
featureFound = true;
const activity = (feature as Feature<Geometry>).get('activity');
if (activity) {
const tooltipElement = this.tooltip.nativeElement;
tooltipElement.innerHTML = activity.name + ' (' + activity.type.name + (this.getBookmarked(activity.osm_id) ? " / favorisiert" : "") + ')';
tooltipElement.style.display = 'block';
tooltipElement.style.left = event.originalEvent.pageX + 'px';
tooltipElement.style.top = (event.originalEvent.pageY - 15) + 'px';
(feature as Feature<Geometry>).setStyle(new Style({
image: new Icon({
src: 'data:image/svg+xml;utf8,' + activity.type.svg,
color: activity.type.color,
scale: this.iconSize,
})
}));
}
});

// MOUSE MOVE NO HOVER

if (!featureFound) {
this.tooltip.nativeElement.style.display = 'none';
this.vectorSource.getFeatures().forEach((feature: Feature<Geometry>) => {
const activity = feature.get('activity');
feature.setStyle(new Style({
image: new Icon({
src: 'data:image/svg+xml;utf8,' + activity.type.svg,
color: activity.type.color,
scale: this.iconSize
})
}));
});
}
}

openDetailPage(activityId: string): void {
this.router.navigate(['/activity-details', activityId]);
}
}
}
2 changes: 1 addition & 1 deletion src/app/services/airtable.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class AirtableService {
id: record["id"] as string,
name: record.fields["name"] as string,
color: record.fields["color"] as string,
svg: record.fields["svg"] as string,
svg: record.fields["svg"] as string
};
});
}),);
Expand Down
3 changes: 2 additions & 1 deletion src/app/types/types.interface.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export interface TypesInterface {
id?: string,
name: string,
color: string
color: string,
svg: string

}

0 comments on commit 3f1e8ff

Please sign in to comment.