Calculate google map zoom attribute for defined range
24. 1. 2023
In this blog we want to share some mathematics and useful formula to use parameter zoom from google maps api used in web application. Our example is a rich web client implemented in angular communicating with rest protocol with Siebel CRM. This web client is a chatbot serving as virtual ai assistant for the swiss insurance company clients for the car breakdown scenarios.
The client needs first identify him self and after specify the breakdown accident in which he is and specify also his location. After these steps are provided the chatbot organizes a help. The location is very important to provide this help to the customer. The chatbot based on the location send a insurance business partner which will provide a help.
For the purpose of localization customer in the chatbot app is localized and he can by pointing to his exactly location precise the marker in the map. For this purpose there is a requirement that the google map has a range of 500m x 800m.
The zoom parameter of google maps is a parameter which determines how much of the world is on one map. The level has 23 values from 0 to 22. For each screen and its resolution has one pixel different distance in the map.
The calculation is based on Mercator projection which is dependent on the latitude. It is possible to calculate using this formula : 156543.03392 * Math.cos(latLng.lat() * Math.PI / 180) / Math.pow(2, zoom). This is based on the assumption that the earth's radius is 6378137m. The formula gives us an idea. How much is a pixel in meters.
Let assume the requirement is to have a google map with window 500m x 800m. The height and width of the googlemap singleton is dynamic in the webapp based on screenresolution and state of the explorer window. Therefore the zoom should be also calculated dynamically based on googlemap height and width.
We need that height x (one pixel dimension) = 800 meters. Let assume our googlemap singleton has height 1000px. 800m = 1000px*156543.03392 * Math.cos(latLng.lat() * Math.PI / 180) / Math.pow(2, zoom). Let assume latitude around Bern which is 47.
The googlemap zoom is : zoom = Math.round(Math.log2(1000px/800m*156543.03392*Math.cos(47 * Math.PI / 180))) .
Here is a block of angular code. We define with mapHeightDistance the range in meters. With the viewModel observable we get the dynamic rendered mapHeight. With setCenter we always calculate the dynamic parameter zoom so we fit to required range for the map.
//distance in meters of vertical map singleton for zoom calculation
const mapHeightDistance=800;
const mapWidthDistance=500;
viewModel$: Observable<ViewModel> = combineLatest([
this.displayPosition$,
this.geolocationPosition$.pipe(startWith(<Marker>undefined)),
this.displayAddress$,
this.showFooter$,
this.geolocationFailure$
]).pipe(
map(([displayPosition, geolocationPosition,
displayAddress, showFooter, geolocationFailure]) => {
return {displayPosition, geolocationPosition, displayAddress, showFooter, geolocationFailure};
}),
tap((v) => console.log('VIEW MODEL', v)),
tap(() => setTimeout(() => {
this.ref.detectChanges();
const footerHeight = this.footerRef ? this.footerRef.nativeElement.offsetHeight : 0;
this.mapHeight = this._chatEntryMap.nativeElement.offsetHeight - footerHeight;
//console.log('set mapHeight:' + this.mapHeight);
})), // google map api is using JSONP, which does not work with default Angular change detection
);
private setCenter(latLng: google.maps.LatLngLiteral) {
this.center = latLng;
/*MPi 23.01.2023 zoom calculation : 800m required vertical max for map*/
this.zoom = Math.round(Math.log2(this.mapHeight/mapHeightDistance*156543.03392*Math.cos(47 * Math.PI / 180)));
//this.zoom = 14; //this.zoom + 0.5; // Hack: Setting the zoom does not work ...
//console.log('zoom mapHeight : '+this.mapHeight+' zoom :'+this.zoom);
}
To conclude this blog, we have provided mathematical formula to calculate google map api zoom parameter to fit to the defined range in the map. The dynamic parameter is the current height and width of the google map and required range in meters. I
Back to Blog