📜 ⬆️ ⬇️

Spreadsheet over Google Maps

Introduction


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


screen0


screen1


Conventions

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.


Overall task


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.


Data for DataContainer


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.


Sample data object
 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 to scale


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.


Saving data


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:


GMapsTable table update 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):


GMapsTable data object generation algorithm


List of all parameters


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.


Sample and source


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