Adding more zoom power to a map

Oracle Developer for over 25 years. Has worked with SQL, PL/SQL, Forms, Reports and Designer but also Java, BPEL and webservices. Currently focusing on APEX.
The case
Wouldn’t it be nice to be able to zoom in further on an APEX-map? Here’s how you can achieve that.
First, you might wonder why need more zoom on a map? Well, one reason for example is being able to click on a given feature to show more information. Especially with many features close together or when using a tablet and having to select one with your (relatively) big fat finger, more space to hit the right “target” is always welcome.
Below is an example of 3 small polygons clustered next to each other on the (default) maximum zoom level of a map in APEX. You can hardly distinct them from each other and clicking on the correct one is pretty hard and takes me several tries.

Now take a look at the same 3 features but zoomed in a fair bit further on a map with a changed maximum zoom-level. The 3 polygons are actually distinguishable from each other and clicking on them with mouse (or finger on a tablet) is a lot easier.

Finding a solution
Before getting to a solution first check out some of the quirks I encountered. Oracle provides a JavaScript interface to the map-region (check here) with methods to get and set the zoomlevel. To get the current zoomlevel you can actually use 2 methods, getMapBboxAndZoomLevel or getMapCenterAndZoomLevel. So when executing this:
apex.region('map-region').getMapCenterAndZoomLevel();
The result could be something like:
{
"center": {
"lng": 4.738595982374818,
"lat": 51.565634949881
},
"zoom": 18
}
In het example above the zoom level is set to “18", which is the default maximum on an APEX map.
Now comes the weird part; for every layer on your map you can define the maximum zoom level at which a layer remains visible. According to the help function the maximum allowed value is “24”… ?! A bit strange, don’t you think? This setting will prove to be important, because if it is NOT set it will default to “18”, the same as the default maximum zoom level.
I also tried entering a larger value than “24” but that is not allowed:

So now we at least know the maxium zoom level we can achieve is very likely 24…
Let’s now turn our attention to the solution. If you’ve read the documentation on the map-interface (see link above) you will have noticed there is no function to set the maximum zoom level for your map. There is a function getMapObject though which will return the MapLibre Map object. MapLibre is essentially the base map Oracle uses for the maps in APEX. Some of the possibilities of MapLibre have been implemented in as attributes in a Map-region in APEX others in the JavaScript interface, but definitely NOT all of them… So after some digging I found a function named setMaxZoom. Sounds a lot like something we could use!
With this knowledge I tried getting a handle on the map-region and set the zoomlevel. I used this simple line of code in the map-initialisation to change the maximum to 24:
apex.region('map-region-static-id').getMapObject().setMaxZoom(24);
I then reloaded the page and something strange happened. The map zoomed automatically to my 3 demo-objects a lot further then before but the objects were gone! I did notice in the lower-left corner the distance-indicator had a much lower value then before though (0.6m vs. 10 m).

I then started zooming out again and my 3 objects suddenly reappeared again around the “10 m” distance-indicator. After some more digging and getting the zoomlevel at the moment the objects appeared again I came to the conclusion the map won’t show them when the actual zoomlevel is higher than the default 18 (fun fact: technically it’s 18.4999, which is rounded down to 18).
Then I thought about the zoom levels that are set on every level. Or more to the point, which are NOT set. I entered value of 24 for the maximum zoomlevel and reloaded the map again. And, lo and behold, the map would zoom nicely to my 3 objects on loading and they were visible too!

I played around a bit zooming in and out and all seemed to work as you’d expect…. for one small detail! At the absolute maximum zoom my objects disappeared again!!! After trying out some stuff I found out they disappear when the actual zoomlevel is 24, but not at 23.99… This is very important because it basically means we cannot set the maximum zoom level to 24, but “only” to 23.99!
Now that I got all the components needed I constructed the solution.
First of all I coded this piece of JavaScript:
let demoMap = (function ($) {
let gMapRegion;
return {
init: function (pStaticId) {
gMapRegion = apex.region(pStaticId);
},
/* Sets the maximum zoom level of the map to the level in the parameter.
Valid values are numbers between 10 and 24. Decimals are allowed.
When setting the level to a value > 18 you must also set the maximum
zoom level of every layer to at least that value or objects will
magically disappear when zooming in beyond the default maximum level.
*/
setMaxZoomLevel: function (pMaxLevel) {
if (pMaxLevel > 10 && pMaxLevel <= 24) {
if (pMaxLevel == 24) {
gMapRegion.getMapObject().setMaxZoom(23.99);
} else {
gMapRegion.getMapObject().setMaxZoom(pMaxLevel);
}
} else {
apex.debug('Invalid value for maximum zoomLevel.');
}
}
}
})(apex.jQuery);
For the sake of this demo I made a seperate function to set the maximum zoom level for a map, you could of course integrate it into the “init” function if you like. To make it easier for fellow devs the function will allow 24 as a maximum level but it will be automatically changed to 23.99 so objects won’t suddenly disappear. I also put in a minium value for the maximum zoomlevel of 10, because I don’t think it will be relevant to be any lower.
Next I added a dynamic action of type “Map Initialized” to my region and added a “Execute JavaScript Code”-action with the following code:
demoMap.init(this.triggeringElement.id);
demoMap.setMaxZoomLevel(24);
Lastly I set the Maximum zoom level of every map-layer to the value “24”.

The result
I now have a map I can zoom to the very maximum and also see really small features. The solution is quit simple in the end and can be easily added to a generic JavaScript library and called in the initialisation of a map!

A few mumblings
I noticed the map will now automatically zoom to the maximum we set when loading it the first time. This might actually be too far. To limit the initial zoom you can set a maximum for this in the attributes of your map region:

This will not affect your defined maximum, so a user can zoom over this level upto your maximum!
(The above solution was made using Oracle APEX 24.2.11 and might or might not work on other versions)



