📜 ⬆️ ⬇️

Printing Yandex.Maps under API 2.x with labels and clusters

Everyone knows that typing API 2.x kernel-card with labels and clusters just won't work. Until now, the map is not built on the canvas, but on the divas with the substrate (background-image). And kanvas favorite browser does not help.
The task was to quickly make a printable version of the map. The number of tags - more than 600 + clusters "out of the box."
Working option under the cut

we initialize the map as usual - we take the zoom and the center from the link
ymaps.ready(function () { var mapTypes = ['yandex#map', 'yandex#satellite', 'yandex#hybrid', 'yandex#publicMap', 'yandex#publicMapHybrid'], map = new ymaps.Map($('#map')[0], { center:[ parseFloat(<?= $request_lat?>), parseFloat(<?= $request_lng?>)], zoom:parseInt(<?= $request_zoom?>), type: mapTypes[<?= $request_mtype ? $request_mtype : 0?>] }); 

do printer-friendly layout for the label
here I must say that the printer-friendly - this means that we do not use the background-image, but do a bunch of divs with images.
My tag icon consists of 2 parts - pictures and the background. both in sprite. therefore such a frantic style. I bring it inline for clarity
  ymaps.layout.storage.add('voina#icon', ymaps.templateLayoutFactory.createClass( '<div style="position: absolute; width: 28px; height: 36px; overflow: hidden;z-index: 0; ">' + '<div style="position:absolute;width:20px;height:20px;overflow:hidden;top:4px;left:4px">' + '<img src="/img/new_buttons_21.png" style="position:absolute;left:$[properties.iconOffset]px;"></div>' + '<img src="/img/buttons7.gif" style="position: absolute; left: -264px; top: -70px; "></div>' )); 

the same with the cluster icon. I did not bother with different sizes of cluster icons for a different number of points inside - it was quickly necessary)
  ymaps.layout.storage.add('voina#cluster', ymaps.templateLayoutFactory.createClass( '<div style="position: absolute; margin: -26px 0 0 -26px; width: 58px; height: 58px; overflow: hidden;z-index: 0; ">' + '<div style="z-index:800;position: absolute; width: 58px; height: 58px; text-align: center; font-size: 13px; line-height: 58px;">$[properties.geoObjects.length]</div>' + '<img src="/img/cluster_big.png" style="position: absolute;"></div>')); 

here we get the container of the leyer card substrate itself
  var $container = map.panes.get('layers').getElement(), 

since the card types are different for statics, we make matches and we get the center of the card
  stMapTypes = {'yandex#map' : 'map', 'yandex#satellite' : 'sat', 'yandex#hybrid' : 'sat,ski', 'yandex#publicMap' : 'pmap'}, center = map.getCenter(), 

size is an ambush. static gives a maximum of 650 to 450. also did not bother - let it be the maximum
A div with a map also needs to be done no more than these sizes.
in a good way, if you make a div with a map of a large size, you need another approach - through the layer.
  size = [650, 450], 

we form a link for statics
  mapUrl = 'http://static-maps.yandex.ru/1.x/?ll='+center[1]+','+center[0]+ '&z='+map.getZoom()+'&l='+stMapTypes[map.getType()]+ '&size='+size[0]+','+size[1]; 

here the magic begins
do a div with absolute positioning and place it in the middle, since the pane binding will be to the center of the viewport. in fact, you had to call map.panes.get ('layers'). getViewport () and read the center. but when loading the pane lies in the middle, and we will not let the map move
  $('<div></div>').css({ position: 'absolute', left: -Math.round(size[0] / 2)+'px', top: -Math.round(size[1] / 2)+'px', zIndex: 800}). 

we insert inside img with a statics
  wrapInner($('<img>').attr({'src':mapUrl, width: size[0], height: size[1], border: '0'})). 

and paste into the leier container over the other elements
  prependTo($container); 

good feature - disables all card events. now neither move nor wonder
  map.events.removeAll(); 

here I add my markers to the map. they are in the variable window.data
  var len = window.data.length; if (len) { for (var i = 0, markers = [ ], properties, latLng; i < len; i++) { latLng = [parseFloat(window.data[i][1]), parseFloat(window.data[i][2])]; markers.push( new ymaps.Placemark(latLng, { iconOffset: -window.data[i][5] * 20 - 1 }, { iconLayout:'voina#icon', iconOffset: [1, 2], openBalloonOnClick: false })); } 

now clusterer What is a margin - I do not remember, but it was on a normal map
  var clusterer = new ymaps.Clusterer({margin: [20]}); 

for icons of clusters we set the layout
  clusterer.options.set('clusterIconLayout', 'voina#cluster'); 

I didn’t want to write this function, but I couldn’t open the clusters in another way
  clusterer.createCluster = function (center, geoObjects) { var cluster = ymaps.Clusterer.prototype.createCluster.call(this, center, geoObjects); //          cluster.events.add('click', function(e) { e.stopImmediatePropagation(); e.preventDefault(); return false; }); return cluster; }; 

add markers to the clusterer
  clusterer.add(markers); 

just in case the clusterer is also muffled
  clusterer.events.removeAll(); 

we add clusterer on the card
  map.geoObjects.add(clusterer); } }); 


TA-dah!!! everything works and prints (if the browser sustains that number of dom objects)
only one bug - two copyrights. when deleting from the map or even hiding mistakes. for uh okay


')
you can see here

Source: https://habr.com/ru/post/150061/


All Articles