
Despite all
my attempts to correct the situation with the technology of loading data onto a map, people all continue and continue to work the old-fashioned way, either downloading all the viewport data at the slightest movement of the map, or simply downloading all the data in general.
As long as the directional meters rasterizes markers into pictures, build super systems of groupings and clusterings and tremble over every extra kilobyte in the scripts, let me tell you the easiest, stable, and most common way to make your life, your users, your cards and your server a little more beautiful.
As will be said later, the conquest of cards consists of 5 steps.
The first one is loading a map (not everything is as simple as it seems), but the second one is downloading data to these same maps.
He is interesting to us.
Currently, there are two common approaches to loading this marker onto a map.
1. We load all data through ajax, or immediately their javascript
2. We pull the server for “what are the objects in our current viewport?”
The first option has the right to life, especially if there are few markers, and the markermanager helps here (to hide the invisible ones), but the second one let's forget as a bad dream.
So, we will consider
that we have a function for loading coordinate box data
$.get( "ajax/load-map-data?SE=" +MySECorner.toString()+ "&NE=" +MyNECorner.toString()+ "&zoom=" +currentZoom, function (data){ //wow! i got the data for map! //for whole visible viewport( and just for it) }); * This source code was highlighted with Source Code Highlighter .
$.get( "ajax/load-map-data?SE=" +MySECorner.toString()+ "&NE=" +MyNECorner.toString()+ "&zoom=" +currentZoom, function (data){ //wow! i got the data for map! //for whole visible viewport( and just for it) }); * This source code was highlighted with Source Code Highlighter .
$.get( "ajax/load-map-data?SE=" +MySECorner.toString()+ "&NE=" +MyNECorner.toString()+ "&zoom=" +currentZoom, function (data){ //wow! i got the data for map! //for whole visible viewport( and just for it) }); * This source code was highlighted with Source Code Highlighter .
$.get( "ajax/load-map-data?SE=" +MySECorner.toString()+ "&NE=" +MyNECorner.toString()+ "&zoom=" +currentZoom, function (data){ //wow! i got the data for map! //for whole visible viewport( and just for it) }); * This source code was highlighted with Source Code Highlighter .
$.get( "ajax/load-map-data?SE=" +MySECorner.toString()+ "&NE=" +MyNECorner.toString()+ "&zoom=" +currentZoom, function (data){ //wow! i got the data for map! //for whole visible viewport( and just for it) }); * This source code was highlighted with Source Code Highlighter .
$.get( "ajax/load-map-data?SE=" +MySECorner.toString()+ "&NE=" +MyNECorner.toString()+ "&zoom=" +currentZoom, function (data){ //wow! i got the data for map! //for whole visible viewport( and just for it) }); * This source code was highlighted with Source Code Highlighter .
$.get( "ajax/load-map-data?SE=" +MySECorner.toString()+ "&NE=" +MyNECorner.toString()+ "&zoom=" +currentZoom, function (data){ //wow! i got the data for map! //for whole visible viewport( and just for it) }); * This source code was highlighted with Source Code Highlighter .
Using it, we kill our server with the impossibility of caching, and the user delays at the slightest map shift (fi 4
aroundme number of times).
How does this crap google work so fast!')
He seems to be loading pictures of his cards ... in small pieces, 256x256 pixels.
Think%% username%, why not do the same?
If we loaded our data in this way then:
- one could just cache on the server
- Moving the map by less than 256 pixels would most likely not result in the loading of new data blocks.
- And since a normal browser supports 4-6 parallel requests to one server (or even more, use jsonp luke! For a couple of subdomains), then we would receive the same amount of data in a couple of streams and, as a result, fry faster
Personally, I belong to the category of perverts, and my implementation of such clever queries, plus the marker manager & clustering takes about 6000 lines.
I will not torment you now with what I will tell you about in subsequent articles.
And just tell
How to make it simple
The implementation is presented for google maps v3, if desired, it is remade in seconds under the yandex card (we take the tiles under Google and display them on Yandex maps , or we implement the described interface initially on Yandex ITile and use their coverter), or, having worked with a file, under google maps v2
In any case, there is a wonderful SparseTileLayer, which can be dismantled from both the api cards and the rest (and which we are using now, since at the time of the end of the development of maps, there were no user options in v3)So create your card type
- function ServerFetchMapType () {
- }
- ServerFetchMapType.prototype.tileSize = new google.maps.Size (256,256);
- ServerFetchMapType.prototype.maxZoom = 32;
- ServerFetchMapType.prototype.name = "Server Tile #s" ;
- ServerFetchMapType.prototype.alt = "Server Data Tile Map Type" ;
- ServerFetchMapType.prototype.getTile = function (coord, zoom, ownerDocument) {
- var addr = this .getAddr (coord, zoom);
- // test - may be we all load this block?
- if (ServerFetchedTiles [addr]) {
- return
- }
- $ .get ( "ajax / load-map-tile?" + addr,
- function (data) {
- ServerFetchedTiles [addr] = data;
- // wow! i got the data just for this tile
- });
- };
- // and add this tile overlay to current map type
- map.overlayMapTypes.insertAt (0, new ServerFetchMapType ());
* This source code was highlighted with Source Code Highlighter .
How not strange -
that's all :)
We have created our own card type, only instead of images we are performing requests to the server.
And requests are of two options - Google like, when we address a tile by its x, y, z or standard ones, by bounding boxing.
The implementation of these methods:
- // we can request tile as tile (x, y, z)
- ServerFetchMapType.prototype.getAddrXY = function (coord, zoom) {
- return "x =" + coord.x + "& y =" + coor.y + "& z =" + zoom;
- }
- // or as latlng box
- ServerFetchMapType.prototype.getAddrLatLng = function (coord, zoom) {
- // helper function for mercator projection
- var mercator = function (point) {
- //
- var numtiles = Math.pow (2, point.zoom);
- var bitmapsize = numtiles * 256;
- var bitmaporigo = bitmapsize / 2;
- var pixelsperlondegree = bitmapsize / 360;
- var pixelsperlonradian = bitmapsize / (2 * Math.PI);
- var lat = bitmaporigo + (pixelsperlondegree * point.x);
- var ged2rad = ((point.t * Math.PI) /180.0);
- var sn = Math.sin (deg2rad);
- var lng = ((bitmaporigo - 0.5 * log ((1 + sn) / (1-sn)) * pixelsperlonradian));
- return new google.maps.LatLng (lat, lng);
- }
- var point1 = {x: coord.x * 256, y: coord.y * 256, z: zoom};
- var point2 = {x: (coord.x + 1) * 256, y: (coord.y + 1) * 256, z: zoom};
- var ne = mercator (point1);
- var sw = mercator (point2);
- return "NE =" + ne.toString () + "& SW =" + sw.toString () + "& z =" + zoom;
- }
* This source code was highlighted with Source Code Highlighter .
* In this case, we didn’t very well realize our mercator function, it’s much better to use the built-in converters (yandex.converter) and projectors (overlay.projection) of the API cards.
What remains
It remains to answer the question - what will happen if you do not have data for downloadable tiles (you are in the middle of the Ural mountains) and why do you need to load the data in this case?
I gave the answer to this question a year and a half ago.
Well, at the end,
let's compare how data loading works on
wikimapia ,
esosedi ,
gdeetotdom and (shame and disgrace to programmers!)
AroundmeBy the way, it should be clarified that the three specified “smart” sites use the z-tile encoding, in fact, the path in the quadtree, but wikimapia, through its API, allows you to request data in xzy addressing.
That's all
I hope that my thoughts will reach people in these thoughts of people in need, if you have questions - ask.
If there are just questions about cartography - also ask, since I had to start
my blog (
blogspot mirror) in my clumsy English, I will always be happy to write about the problems of exciting masses.
Well, I will go to finish the second article in which I will tell a lot of new secrets, not previously announced in Habré. And you stock up on coffee and chat