1
1
import { Component , ElementRef , OnInit , ViewChild } from '@angular/core' ;
2
- import { Map , MapBrowserEvent , View } from 'ol' ;
2
+ import { Map , View } from 'ol' ;
3
3
import { Tile as TileLayer , Vector as VectorLayer } from 'ol/layer' ;
4
4
import { OSM , Vector as VectorSource } from 'ol/source' ;
5
5
import Feature from 'ol/Feature' ;
6
- import { Geometry , Point } from 'ol/geom' ;
7
- import { Circle , Fill , Stroke , Style } from 'ol/style' ;
8
- import { fromLonLat } from 'ol/proj' ;
9
- import { Router } from '@angular/router' ;
10
- import { AirtableService } from '../../services/airtable.service' ;
11
- import { NgStyle } from "@angular/common" ;
6
+ import { Point , Geometry } from 'ol/geom' ;
7
+ import { Style , Icon } from 'ol/style' ;
8
+ import { fromLonLat } from 'ol/proj' ;
9
+ import { Router } from '@angular/router' ;
10
+ import { AirtableService } from '../../services/airtable.service' ;
11
+ import { MapBrowserEvent } from 'ol' ;
12
+ import { NgStyle } from "@angular/common" ;
12
13
13
14
@Component ( {
14
15
selector : 'app-map' ,
@@ -20,126 +21,128 @@ import {NgStyle} from "@angular/common";
20
21
styleUrls : [ './map.component.scss' ]
21
22
} )
22
23
export class MapComponent implements OnInit {
23
- map ! : Map ;
24
- vectorSource ! : VectorSource ;
24
+ map ! : Map ;
25
+ vectorSource ! : VectorSource ;
25
26
26
- @ViewChild ( 'tooltip_map' , { static : true } ) tooltip ! : ElementRef ;
27
-
28
- constructor ( private router : Router , private airtableService : AirtableService ) {
29
- }
30
-
31
- getBookmarked ( osm_id : number | null | undefined ) {
32
- const item = localStorage . getItem ( "savedLocations" )
33
- if ( item ) {
34
- const savedLocations = JSON . parse ( item )
35
- return savedLocations . includes ( osm_id )
36
- }
37
- }
38
-
39
- ngOnInit ( ) : void {
40
- this . vectorSource = new VectorSource ( ) ;
41
- const vectorLayer = new VectorLayer ( {
42
- source : this . vectorSource
43
- } ) ;
44
-
45
- this . map = new Map ( {
46
- target : 'map' ,
47
- layers : [
48
- new TileLayer ( {
49
- source : new OSM ( )
50
- } ) ,
51
- vectorLayer
52
- ] ,
53
- view : new View ( {
54
- center : fromLonLat ( [ 8.970869314606485 , 47.73981783654207 ] ) ,
55
- zoom : 3 ,
56
- minZoom : 12 ,
57
- maxZoom : 25
58
- } )
59
- } ) ;
60
-
61
- this . map . on ( 'click' , this . handleMapClick . bind ( this ) ) ;
62
- this . map . on ( 'pointermove' , this . handlePointerMove . bind ( this ) ) ;
63
-
64
- this . airtableService . getActivityList ( ) . subscribe ( activities => {
65
- activities . forEach ( activity => {
66
- const feature = new Feature ( {
67
- geometry : new Point ( fromLonLat ( [ activity . longitude , activity . latitude ] ) ) ,
68
- activity : activity
69
- } ) ;
27
+ iconSize = 0.15 ;
70
28
71
- const local = this . getBookmarked ( activity . osm_id ) ;
72
- const borderSize = local ? 10.0 : 0.75
73
- const color = local ? "gold" : "black"
74
-
75
- feature . setStyle ( new Style ( {
76
- image : new Circle ( {
77
- radius : 8 ,
78
- fill : new Fill ( { color : activity . type . color } ) ,
79
- stroke : new Stroke ( { color : color , width : borderSize } )
80
- } )
81
- } ) ) ;
82
-
83
- this . vectorSource . addFeature ( feature ) ;
84
- } ) ;
85
- } ) ;
86
-
87
- }
29
+ @ViewChild ( 'tooltip_map' , { static : true } ) tooltip ! : ElementRef ;
88
30
89
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
90
- handleMapClick ( event : MapBrowserEvent < any > ) {
91
- this . map . forEachFeatureAtPixel ( event . pixel , ( feature ) => {
92
- const activity = ( feature as Feature < Geometry > ) . get ( 'activity' ) ;
93
- if ( activity ) {
94
- this . openDetailPage ( activity . osm_id ) ;
95
- }
96
- } ) ;
31
+ constructor ( private router : Router , private airtableService : AirtableService ) { }
32
+
33
+ getBookmarked ( osm_id : number | null | undefined ) {
34
+ const item = localStorage . getItem ( "savedLocations" )
35
+ if ( item ) {
36
+ const savedLocations = JSON . parse ( item )
37
+ return savedLocations . includes ( osm_id )
97
38
}
98
-
99
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
100
- handlePointerMove ( event : MapBrowserEvent < any > ) {
101
- const pixel = this . map . getEventPixel ( event . originalEvent ) ;
102
- let featureFound = false ;
103
-
104
- this . map . forEachFeatureAtPixel ( pixel , ( feature ) => {
105
- featureFound = true ;
106
- const activity = ( feature as Feature < Geometry > ) . get ( 'activity' ) ;
107
- if ( activity ) {
108
- const tooltipElement = this . tooltip . nativeElement ;
109
- const borderSize = this . getBookmarked ( activity . osm_id ) ? 5.0 : 0.75
110
- const color = this . getBookmarked ( activity . osm_id ) ? "gold" : "black"
111
- tooltipElement . innerHTML = activity . name + ' (' + activity . type . name + ( this . getBookmarked ( activity . osm_id ) ? " / favorisiert" : "" ) + ')' ;
112
- tooltipElement . style . display = 'block' ;
113
- tooltipElement . style . left = event . originalEvent . pageX + 'px' ;
114
- tooltipElement . style . top = ( event . originalEvent . pageY - 15 ) + 'px' ;
115
- ( feature as Feature < Geometry > ) . setStyle ( new Style ( {
116
- image : new Circle ( {
117
- radius : 10 ,
118
- fill : new Fill ( { color : activity . type . color } ) ,
119
- stroke : new Stroke ( { color : color , width : borderSize } )
120
- } )
121
- } ) ) ;
122
- }
39
+ return false ;
40
+ }
41
+
42
+ ngOnInit ( ) : void {
43
+ this . vectorSource = new VectorSource ( ) ;
44
+ const vectorLayer = new VectorLayer ( {
45
+ source : this . vectorSource
46
+ } ) ;
47
+
48
+ this . map = new Map ( {
49
+ target : 'map' ,
50
+ layers : [
51
+ new TileLayer ( {
52
+ source : new OSM ( )
53
+ } ) ,
54
+ vectorLayer
55
+ ] ,
56
+ view : new View ( {
57
+ center : fromLonLat ( [ 8.970869314606485 , 47.73981783654207 ] ) ,
58
+ zoom : 3 ,
59
+ minZoom : 10 ,
60
+ maxZoom : 25
61
+ } )
62
+ } ) ;
63
+
64
+ this . map . on ( 'click' , this . handleMapClick . bind ( this ) ) ;
65
+ this . map . on ( 'pointermove' , this . handlePointerMove . bind ( this ) ) ;
66
+
67
+ // INITIALIZE
68
+
69
+ this . airtableService . getActivityList ( ) . subscribe ( activities => {
70
+ activities . forEach ( activity => {
71
+ const local = this . getBookmarked ( activity . osm_id ) ;
72
+ console . log ( `Activity: ${ activity . name } , Bookmarked: ${ local } , Color: ${ activity . type . color } ` ) ;
73
+
74
+ const feature = new Feature ( {
75
+ geometry : new Point ( fromLonLat ( [ activity . longitude , activity . latitude ] ) ) ,
76
+ activity : activity
123
77
} ) ;
124
-
125
- if ( ! featureFound ) {
126
- this . tooltip . nativeElement . style . display = 'none' ;
127
- this . vectorSource . getFeatures ( ) . forEach ( ( feature : Feature < Geometry > ) => {
128
- const activity = feature . get ( 'activity' ) ;
129
- const borderSize = this . getBookmarked ( activity . osm_id ) ? 5.0 : 0.75
130
- const color = this . getBookmarked ( activity . osm_id ) ? "gold" : "black"
131
- feature . setStyle ( new Style ( {
132
- image : new Circle ( {
133
- radius : 8 ,
134
- fill : new Fill ( { color : activity . type . color } ) ,
135
- stroke : new Stroke ( { color : color , width : borderSize } )
136
- } )
137
- } ) ) ;
138
- } ) ;
139
- }
78
+
79
+ feature . setStyle ( new Style ( {
80
+ image : new Icon ( {
81
+ src : 'data:image/svg+xml;utf8,' + activity . type . svg ,
82
+ color : activity . type . color ,
83
+ size : [ this . iconSize , this . iconSize ]
84
+ } )
85
+ } ) ) ;
86
+
87
+ this . vectorSource . addFeature ( feature ) ;
88
+ } ) ;
89
+ } ) ;
90
+ }
91
+
92
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
93
+ handleMapClick ( event : MapBrowserEvent < any > ) {
94
+ this . map . forEachFeatureAtPixel ( event . pixel , ( feature ) => {
95
+ const activity = ( feature as Feature < Geometry > ) . get ( 'activity' ) ;
96
+ if ( activity ) {
97
+ this . openDetailPage ( activity . osm_id ) ;
98
+ }
99
+ } ) ;
100
+ }
101
+
102
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
103
+ handlePointerMove ( event : MapBrowserEvent < any > ) {
104
+ const pixel = this . map . getEventPixel ( event . originalEvent ) ;
105
+ let featureFound = false ;
106
+
107
+ // HOVER
108
+
109
+ this . map . forEachFeatureAtPixel ( pixel , ( feature ) => {
110
+ featureFound = true ;
111
+ const activity = ( feature as Feature < Geometry > ) . get ( 'activity' ) ;
112
+ if ( activity ) {
113
+ const tooltipElement = this . tooltip . nativeElement ;
114
+ tooltipElement . innerHTML = activity . name + ' (' + activity . type . name + ( this . getBookmarked ( activity . osm_id ) ? " / favorisiert" : "" ) + ')' ;
115
+ tooltipElement . style . display = 'block' ;
116
+ tooltipElement . style . left = event . originalEvent . pageX + 'px' ;
117
+ tooltipElement . style . top = ( event . originalEvent . pageY - 15 ) + 'px' ;
118
+ ( feature as Feature < Geometry > ) . setStyle ( new Style ( {
119
+ image : new Icon ( {
120
+ src : 'data:image/svg+xml;utf8,' + activity . type . svg ,
121
+ color : activity . type . color ,
122
+ scale : this . iconSize ,
123
+ } )
124
+ } ) ) ;
125
+ }
126
+ } ) ;
127
+
128
+ // MOUSE MOVE NO HOVER
129
+
130
+ if ( ! featureFound ) {
131
+ this . tooltip . nativeElement . style . display = 'none' ;
132
+ this . vectorSource . getFeatures ( ) . forEach ( ( feature : Feature < Geometry > ) => {
133
+ const activity = feature . get ( 'activity' ) ;
134
+ feature . setStyle ( new Style ( {
135
+ image : new Icon ( {
136
+ src : 'data:image/svg+xml;utf8,' + activity . type . svg ,
137
+ color : activity . type . color ,
138
+ scale : this . iconSize
139
+ } )
140
+ } ) ) ;
141
+ } ) ;
140
142
}
143
+ }
141
144
142
145
openDetailPage ( activityId : string ) : void {
143
146
this . router . navigate ( [ '/activity-details' , activityId ] ) ;
144
147
}
145
- }
148
+ }
0 commit comments