1
+ import { useNavigation } from '#context/Navigation.tsx'
1
2
import { useParameters } from '#context/Parameters.js'
2
- import { Center , Map , ZoomIn , ZoomOut } from '#icons/LucideIcon.js'
3
+ import { Lock , Map , Unlock , ZoomIn , ZoomOut } from '#icons/LucideIcon.js'
3
4
import { createMap } from '#map/createMap.js'
4
5
import { geoJSONPolygonFromCircle } from '#map/geoJSONPolygonFromCircle.js'
5
- import { getLocationsBounds } from '#map/getLocationsBounds.js '
6
+ import { getLocationsBounds } from '#map/getLocationsBounds.ts '
6
7
import { glyphFonts } from '#map/glyphFonts.js'
7
8
import {
8
9
defaultLocationSourceColor ,
@@ -11,7 +12,13 @@ import {
11
12
import { type Geolocation_14201 } from '@hello.nrfcloud.com/proto-map/lwm2m'
12
13
import type { Map as MapLibreGlMap } from 'maplibre-gl'
13
14
import { ScaleControl } from 'maplibre-gl'
14
- import { createEffect , createMemo , onCleanup } from 'solid-js'
15
+ import {
16
+ createEffect ,
17
+ createMemo ,
18
+ createSignal ,
19
+ onCleanup ,
20
+ Show ,
21
+ } from 'solid-js'
15
22
16
23
import './Location.css'
17
24
@@ -29,11 +36,18 @@ const byAge = (loc1: Geolocation_14201, loc2: Geolocation_14201) =>
29
36
30
37
export const Card = ( props : { locations : Geolocation_14201 [ ] } ) => {
31
38
const parameters = useParameters ( )
39
+ const location = useNavigation ( )
40
+ const [ locked , setLocked ] = createSignal ( true )
32
41
33
42
let ref ! : HTMLDivElement
34
43
let map : MapLibreGlMap
35
44
36
- const bounds = createMemo ( ( ) => getLocationsBounds ( props . locations ) )
45
+ const centerLocation = createMemo ( ( ) =>
46
+ props . locations . find (
47
+ ( { Resources } ) =>
48
+ Resources [ 6 ] === location . current ( ) ?. deviceMap ?. centerLocationSource ,
49
+ ) ,
50
+ )
37
51
38
52
createEffect ( ( ) => {
39
53
const mostRecent = props . locations . sort ( byAge ) [ 0 ]
@@ -42,7 +56,7 @@ export const Card = (props: { locations: Geolocation_14201[] }) => {
42
56
43
57
const {
44
58
Resources : { 0 : lat , 1 : lng } ,
45
- } = mostRecent
59
+ } = centerLocation ( ) ?? mostRecent
46
60
47
61
map = createMap (
48
62
ref ,
@@ -65,18 +79,20 @@ export const Card = (props: { locations: Geolocation_14201[] }) => {
65
79
const lat = Resources [ 0 ]
66
80
const acc = Resources [ 3 ] ?? 500
67
81
const src = Resources [ 6 ]
82
+
68
83
// Data for Hexagon
69
84
const locationAreaSourceId = `center-circle-source-${ src } `
70
- map . addSource (
71
- locationAreaSourceId ,
72
- geoJSONPolygonFromCircle ( [ lng , lat ] , acc , 6 , Math . PI / 2 ) ,
73
- )
85
+ map . addSource ( locationAreaSourceId , {
86
+ ...geoJSONPolygonFromCircle ( [ lng , lat ] , acc , 6 , Math . PI / 2 ) ,
87
+ // This will ensure that the polygon is drawn even at low zoom levels
88
+ // See https://docs.mapbox.com/help/troubleshooting/working-with-large-geojson-data/#tolerance
89
+ tolerance : 0.001 ,
90
+ } )
74
91
// Render Hexagon
75
92
map . addLayer ( {
76
93
id : `center-circle-layer-${ src } ` ,
77
94
type : 'line' ,
78
- source : `center-circle-source-${ src } ` ,
79
- layout : { } ,
95
+ source : locationAreaSourceId ,
80
96
paint : {
81
97
'line-color' :
82
98
locationSourceColors [ src ] ?? defaultLocationSourceColor ,
@@ -105,16 +121,29 @@ export const Card = (props: { locations: Geolocation_14201[] }) => {
105
121
} ,
106
122
} )
107
123
}
124
+ } )
108
125
109
- map . fitBounds ( bounds ( ) , {
110
- padding : 20 ,
111
- maxZoom : 16 ,
112
- } )
126
+ onCleanup ( ( ) => {
127
+ map ?. remove ( )
113
128
} )
114
129
} )
115
130
116
- onCleanup ( ( ) => {
117
- map ?. remove ( )
131
+ createEffect ( ( ) => {
132
+ if ( centerLocation ( ) === undefined ) return
133
+ map . fitBounds ( getLocationsBounds ( [ centerLocation ( ) ! ] ) , {
134
+ padding : 40 ,
135
+ maxZoom : 16 ,
136
+ } )
137
+ } )
138
+
139
+ createEffect ( ( ) => {
140
+ if ( locked ( ) ) {
141
+ map . scrollZoom . disable ( )
142
+ map . dragPan . disable ( )
143
+ } else {
144
+ map . scrollZoom . enable ( )
145
+ map . dragPan . enable ( )
146
+ }
118
147
} )
119
148
120
149
return (
@@ -123,17 +152,28 @@ export const Card = (props: { locations: Geolocation_14201[] }) => {
123
152
< button type = "button" onClick = { ( ) => map ?. zoomIn ( ) } >
124
153
< ZoomIn />
125
154
</ button >
126
- < button
127
- type = "button"
128
- onClick = { ( ) =>
129
- map ?. fitBounds ( bounds ( ) , {
130
- padding : 20 ,
131
- maxZoom : 16 ,
132
- } )
155
+ < Show
156
+ when = { locked ( ) }
157
+ fallback = {
158
+ < button
159
+ type = "button"
160
+ onClick = { ( ) => {
161
+ setLocked ( true )
162
+ } }
163
+ >
164
+ < Lock />
165
+ </ button >
133
166
}
134
167
>
135
- < Center />
136
- </ button >
168
+ < button
169
+ type = "button"
170
+ onClick = { ( ) => {
171
+ setLocked ( false )
172
+ } }
173
+ >
174
+ < Unlock />
175
+ </ button >
176
+ </ Show >
137
177
< button type = "button" onClick = { ( ) => map ?. zoomOut ( ) } >
138
178
< ZoomOut />
139
179
</ button >
0 commit comments