Have you ever needed to display large data sets with reference to a map? At work, I needed to display orders grouped by latitude and longitude. And not just a static table, but a dynamic one, with different details for a different map approximation.
Unfortunately (or fortunately?), I did not find ready-made solutions. Google Maps allows you to overlay markers and shapes on maps, but these methods provide too little information. With Yandex cards it turned out no better. But Google Maps has a custom overlay mechanism with HTML content. And to encapsulate this work with maps and overlays, I created the GMapsTable JavaScript library. Perhaps someone it will be interesting or useful. Working example
To avoid confusion, the zoom parameter will be called the map approximation, and the scale - the scale. The first relates to the Google Maps API, and the second to the described library.
So what do we have? Some data source (for example, a server with a database that processes and sends data in JSON format) and a web page with JavaScript that requests data and visualizes it on Google Maps.
The data are of an accumulative nature (in my case, each area can be assigned to: the number of orders, customers, and the average amount). Therefore, the data can and should be displayed with different details for different approximations.
Main content of HTML page for GMapsTable:
.. <head>: <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_KEY"></script> <script src="http://www.aivanf.com/static/gmt/gmapstable.js"></script> .. <body>: <div id="map"></div>
GMapsTable allows to abstract from interaction with GoogleMaps API. You only need to provide the appropriate object with the data. Time to go to javascript! To use GMapsTable, you only need to get the DataContainer object for your div map:
// : ID div' // GoogleMaps, // var container = new DataContainer("map", { zoom: 9, center: {lat: 55.7558, lng: 37.6173}, mapTypeId: 'roadmap' });
And then you need to pass a couple of functions:
container.dataLoader = function (scale, borders) { ... container.processData(some_data); } container.scaler = function (zoom) { ... return - ; }
But what exactly is to write inside functions? .. First, let's figure out how GMapsTable works.
DataContainer
deals with the display of your data and takes care of when it should be updated. At the very beginning and when the approximation and the boundaries of the “camera” change, it tries to use the stored data, and if not, it calls the dataLoader
function. You need to generate an object with data and pass it to the DataContainer.processData function. The structure of the object should be as follows:
data: { minLat: float, difLat: float, minLon: float, difLon: float, scale: int, table: [ [value, value, ...], [value, value, ...], ... ], tocache: boolean }
The value
can be a number, a string, or any object if you specify your own table cell formatting function. The scale ( sale
) is an integer indicating how many parts the latitude and longitude units should be divided. The tocache
parameter specifies whether data for the current scale should be saved and no longer requested.
data: { minLat: 55.0, difLat: 2.0, minLon: 37.0, difLon: 1.0, scale: 2, table: [ [1, 3, 0, 1], [0, 1, 2, 0] ], tocache: true }
Here the data covers the area from 55.0, 37.0 to 57.0, 38.0 and divide each unit of latitude and longitude into 2 parts (it turns out that one cell of latitude-longitude is divided into 4 parts). It also indicates here that for a given scale this is complete data, and they should be saved for future use.
Zoom is the Google Maps API parameter, an integer between 1 (world map) and 22 (street). It is inconvenient and impractical to request and store data for each approximation unit, therefore GMapsTable converts it to a scale - a number indicating how many parts the latitude and longitude unit should be divided into.
To display when changing the scale was instant, GMapsTable stores data sets for some (or all) scales. For example, I had coordinates with almost all of Russia - about 42 thousand cells for a scale of 10 (500 KB, it is fairly easily stored and processed in my desktop browser) and 17 million for a scale of 200 (several MB, causing significant suspension) . Therefore, the server estimates the number of cells of all data, and if there are few of them, it sends data from the entire database, otherwise only for the requested region. It turns out this algorithm:
Borders ( bounds
) is a JavaScript object with minlat, maxlat, minlon, maxlon
— current Google Maps boundaries and a good indent.
In your implementation of the dataLoader
you can safely ignore the arguments if there is no need to use different granularities for different scales or if your data does not cover such a large region. Just transfer the data and their boundaries in latitude and longitude and scale
, how much you break the units of latitude-longitude. But for the dataLoader
completeness, I suggest this behavior of the dataLoader
function (or the server it is accessing):
You can specify the following parameters for the DataContainer:
1) scaler(zoom)
- converts an approximation from GoogleMaps to a scale for GMapsTable. Both are integers.
2) dataLoader(scale, borders)
- called when new data is needed. Must pass a data object to DataContainer.processData(data)
.
The borders
argument is a JavaScript object with the minlat, maxlat, minlon, maxlon
— the current borders of Google Maps and a good indent.
3) tableBeforeInit(map, table, data)
- called before the table begins to fill with cells. The map
argument is a Google Maps object, table
is the HTML element of the created table, and data
is the data
object you provided for the current scale. Here you can set up a table, some variables using current data or current map parameters.
4) cellFormatter(td, val)
- called to fill the cell. td
is an HTML element, a table cell. val
is data from your data object. Here you can easily customize the display of several values or fill color in accordance with any parameters.
5) boundsChangedListener(zoom)
- called when the boundaries of Google Maps change.
6) minZoomLevel
, maxZoomLevel
- variables for the minimum and maximum map approximation. Integers between 1 (world map) and 22 (street).
For successful operation DataContainer only the first two functions are necessary.
A full and well-commented example of use: HTML-page and JS-code .
And also there is a GMapsTable in GitHub .
Source: https://habr.com/ru/post/330920/
All Articles