11/**
2- * Returns the base map style configuration for MapLibre
2+ * Returns the base map style configuration for MapLibre with Google Maps-like styling
33 * @returns {Object } Base map style configuration
44 */
55function getBaseMapStyle ( ) {
66 return {
77 version : 8 ,
88 sources : {
9- osm : {
9+ // Using CartoDB Positron for a cleaner, Google Maps-like appearance
10+ "cartodb-light" : {
1011 type : "raster" ,
11- tiles : [ "https://tile.openstreetmap.org/{z}/{x}/{y}.png" ] ,
12+ tiles : [
13+ "https://a.basemaps.cartocdn.com/light_all/{z}/{x}/{y}@2x.png" ,
14+ "https://b.basemaps.cartocdn.com/light_all/{z}/{x}/{y}@2x.png" ,
15+ "https://c.basemaps.cartocdn.com/light_all/{z}/{x}/{y}@2x.png" ,
16+ "https://d.basemaps.cartocdn.com/light_all/{z}/{x}/{y}@2x.png" ,
17+ ] ,
1218 tileSize : 256 ,
13- attribution : "© OpenStreetMap contributors" ,
19+ attribution : "© OpenStreetMap contributors, © CARTO" ,
20+ maxzoom : 19 ,
21+ } ,
22+ // Satellite layer for satellite view
23+ satellite : {
24+ type : "raster" ,
25+ tiles : [
26+ "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}" ,
27+ ] ,
28+ tileSize : 256 ,
29+ attribution :
30+ "© Esri, DigitalGlobe, GeoEye, Earthstar Geographics, CNES/Airbus DS, USDA, USGS, AeroGRID, IGN, and the GIS User Community" ,
31+ maxzoom : 19 ,
1432 } ,
1533 } ,
1634 layers : [
1735 {
18- id : "osm " ,
36+ id : "base-map " ,
1937 type : "raster" ,
20- source : "osm " ,
38+ source : "cartodb-light " ,
2139 minzoom : 0 ,
2240 maxzoom : 19 ,
2341 } ,
@@ -26,19 +44,119 @@ function getBaseMapStyle() {
2644}
2745
2846/**
29- * Initializes the map with the base map configuration
47+ * Initializes the map with the base map configuration and Google Maps-like settings
3048 * @param {string } containerId - ID of the HTML element to contain the map
3149 * @returns {Object } Initialized MapLibre map instance
3250 */
3351function initializeMap ( containerId ) {
34- return new maplibregl . Map ( {
52+ const map = new maplibregl . Map ( {
3553 container : containerId ,
3654 style : getBaseMapStyle ( ) ,
37- center : [ 0 , 20 ] ,
55+ center : [ 0 , 20 ] , // Centered on equator with slight northern bias for better land visibility
3856 zoom : 2 ,
57+ minZoom : 1 ,
3958 maxZoom : 19 ,
40- // Using the default preserveDrawingBuffer value (false) improves
41- // rendering performance when displaying many features.
59+ // Improved performance settings
4260 preserveDrawingBuffer : false ,
61+ // Google Maps-like interaction settings
62+ doubleClickZoom : true ,
63+ dragRotate : false , // Disable rotation for simpler interaction
64+ pitchWithRotate : false ,
65+ touchZoomRotate : false ,
66+ // Smooth animations
67+ trackResize : true ,
68+ } ) ;
69+
70+ // Add map style switcher control
71+ map . on ( "load" , ( ) => {
72+ // Add satellite layer but keep it hidden initially
73+ if ( ! map . getLayer ( "satellite-layer" ) ) {
74+ map . addLayer (
75+ {
76+ id : "satellite-layer" ,
77+ type : "raster" ,
78+ source : "satellite" ,
79+ layout : {
80+ visibility : "none" ,
81+ } ,
82+ minzoom : 0 ,
83+ maxzoom : 19 ,
84+ } ,
85+ "base-map"
86+ ) ;
87+ }
88+
89+ // Create custom control for map style switching
90+ class StyleSwitchControl {
91+ constructor ( ) {
92+ this . isLight = true ;
93+ }
94+
95+ onAdd ( map ) {
96+ this . map = map ;
97+ this . container = document . createElement ( "div" ) ;
98+ this . container . className = "maplibregl-ctrl maplibregl-ctrl-group" ;
99+
100+ // Satellite button
101+ this . satelliteBtn = document . createElement ( "button" ) ;
102+ this . satelliteBtn . className = "maplibregl-ctrl-icon" ;
103+ this . satelliteBtn . type = "button" ;
104+ this . satelliteBtn . title = "Satellite View" ;
105+ this . satelliteBtn . innerHTML = "🛰️" ;
106+ this . satelliteBtn . style . fontSize = "14px" ;
107+ this . satelliteBtn . onclick = ( ) => this . toggleSatellite ( ) ;
108+
109+ // Terrain button
110+ this . terrainBtn = document . createElement ( "button" ) ;
111+ this . terrainBtn . className = "maplibregl-ctrl-icon" ;
112+ this . terrainBtn . type = "button" ;
113+ this . terrainBtn . title = "Map View" ;
114+ this . terrainBtn . innerHTML = "🗺️" ;
115+ this . terrainBtn . style . fontSize = "14px" ;
116+ this . terrainBtn . onclick = ( ) => this . showTerrain ( ) ;
117+
118+ this . container . appendChild ( this . satelliteBtn ) ;
119+ this . container . appendChild ( this . terrainBtn ) ;
120+
121+ return this . container ;
122+ }
123+
124+ onRemove ( ) {
125+ this . container . parentNode . removeChild ( this . container ) ;
126+ this . map = undefined ;
127+ }
128+
129+ toggleSatellite ( ) {
130+ if (
131+ this . map . getLayoutProperty ( "satellite-layer" , "visibility" ) ===
132+ "visible"
133+ ) {
134+ this . map . setLayoutProperty ( "satellite-layer" , "visibility" , "none" ) ;
135+ this . map . setLayoutProperty ( "base-map" , "visibility" , "visible" ) ;
136+ this . satelliteBtn . style . backgroundColor = "" ;
137+ } else {
138+ this . map . setLayoutProperty (
139+ "satellite-layer" ,
140+ "visibility" ,
141+ "visible"
142+ ) ;
143+ this . map . setLayoutProperty ( "base-map" , "visibility" , "none" ) ;
144+ this . satelliteBtn . style . backgroundColor = "#1a73e8" ;
145+ this . satelliteBtn . style . color = "white" ;
146+ }
147+ }
148+
149+ showTerrain ( ) {
150+ this . map . setLayoutProperty ( "satellite-layer" , "visibility" , "none" ) ;
151+ this . map . setLayoutProperty ( "base-map" , "visibility" , "visible" ) ;
152+ this . satelliteBtn . style . backgroundColor = "" ;
153+ this . satelliteBtn . style . color = "" ;
154+ }
155+ }
156+
157+ // Add the style switch control
158+ map . addControl ( new StyleSwitchControl ( ) , "top-left" ) ;
43159 } ) ;
160+
161+ return map ;
44162}
0 commit comments