Использование API Яндекс.Карт для работы с произвольными подложками



    Что общего у трех картинок сверху? На левой — часть Санкт-Петербурга из OpenStreetMap. На центральной — карта из Lineage 2. На правой — автомобильные пробки Москвы на подложке от Google. А объединяет эти изображения новое API Яндекс.Карт, вышедшее совсем недавно.

    Одной из особенностей API 2.0 является очень простая в использовании поддержка произвольных подложек. Вам не обязательно использовать карты Яндекса для своего ресурса. Никто не мешает скрестить подложку от OpenStreetMap и мощное API от Яндекса для реализации функционала карты.

    Хотите показать на OpenStreetMap область доставки вашей пиццерии? Расположить на карте монстров очередной MMORPG? Отобразить Яндекс.Пробки на карте от Google? Нет ничего проще!


    Пример 1. Яндекс.Пробки + Google.Карты


    живой пример

        var map = new ym.Map('map', {
            center: [55.744, 37.587],
            zoom: 12,
            type: null // что-бы не загружался слой "Схема" Яндекс.Карт
        }, {});
    
        var googleLayer = new ym.Layer('http://mt0.google.com/vt/lyrs=m@176000000&hl=ru&%c', {
            projection: ym.projection.sphericalMercator,
            // указываем проекцию слоя Google.Карт
            tileTransparent: true
        });
        map.layers.add(googleLayer);
    
        map.controls.add(new ym.control.TrafficControl({
            shown: true
        }), {
            left: 5,
            top: 5
        });
    

    Разберем, что же мы понаписали. В первую очередь стоит обратить внимание на класс Layer, именно с помощью него создаются новые слои карты. Входными параметрами являются шаблон url'а тайлов и опции. Описание формата шаблона есть в документации. В данном же примере интерес представляет опция projection, которая говорит API о проекции слоя. Дело в том, что API Яндекс.Карт использует проекцию WGS 84, которая немного отличается от Spherical Mercator, используемой в OSM и Google. Поэтому при добавлении слоя нужно указать его проекцию, в противном случае, если вы добавите точку по координатам вашего дома, то визуально она может оказаться на стороннем слое не там, где вы ее ожидали увидеть.

    Пример 2. OpenStreetMap + Графика API Яндекс.Карт


    живой пример

        var map = new ym.Map('map', {
            center: [59.947, 30.325],
            zoom: 13,
            type: null // что-бы не загружался слой "Схема" Яндекс.Карт
        }, {});
    
        var osmLayer = new ym.Layer('http://otile%d.mqcdn.com/tiles/1.0.0/osm/%z/%x/%y.png', {
            projection: ym.projection.sphericalMercator,
            // указываем проекцию слоя OSM
            tileTransparent: true
        });
        map.layers.add(osmLayer);
    
        var train = new ym.Placemark([59.928815, 30.362311], {
            hintContent: "Московский вокзал"
        }, {
            preset: "twirl#trainIcon"
        })
        map.geoObjects.add(train);
    
        var pizza = new ym.Placemark([59.954327, 30.30698], {
            balloonContent: "Пиццерия"
        }, {
            preset: "twirl#cafeIcon"
        })
        map.geoObjects.add(pizza);
    
        var area = new ym.Circle([[59.954327, 30.30698], 1400], {
            hintContent: "Область доставки"
        }, {
            strokeColor: "#7C444399",
            strokeWidth: 2,
            fillColor: "#FFFFFF66",
            hintHideTimeout: 100
        });
    
        area.events.add("mouseenter", function(e) {
            this.options.set({
                strokeColor: "#7C4443BB",
                strokeWidth: 4,
                fillColor: "#FFFFFF99"
            })
        }, area);
    
        area.events.add("mouseleave", function(e) {
            this.options.set({
                strokeColor: "#7C444399",
                strokeWidth: 2,
                fillColor: "#FFFFFF66"
            })
        }, area);
    
        var geometry = ym.geometry.LineString.fromEncodedCoordinates("-nCSA99KzwFdBwAA0v3__2kBAABk-___" + "SgYAAKHO__8bEQAAQHX__y0BAAB_____8gIAAFcBAAAREAAAXej__-EEAAAo_v__mwIAANH8__9zAwAAdfj__" + "wAJAACBAAAAbgEAAK0BAAAaAgAA2wMAAKAEAAB_____VgAAAAoHAAACAQAArAAAAHcFAAAl_P__" + "3gMAAAAAAAAyAwAA1wAAAMYCAACtAQAAcAIAAFkCAAA="); // закодированая геометрия линии
        var line = new ym.Polyline(geometry, {}, {
            strokeWidth: 2,
            strokeStyle: "longdash"
        });
        map.geoObjects.add(line);
    
        map.geoObjects.add(area);
    
        pizza.balloon.open();
    

    Касательно добавления слоя, данный пример мало отличается от предыдущего. Разве что только в шаблоне используются параметры %d, %z, x и %y, а не %c как в первом примере.
    Описание параметров есть в документации.

    Пример 3. Создание своих карт


    живой пример

        // декартова система координат
        var projection = new ym.projection.Cartesian([[0, 0], [100, 100]]);
    
        var layer = function(){
            return new ym.Layer(function(tile, zoom) {
                return "http://mt.gmapuploader.com/tiles/bneaLXS8B7/tile-" + zoom + "-" + (tile[1] * Math.pow(2, zoom) + tile[0]) + ".jpg";
            });
        };
        var lineageMap = new ym.MapType('LineageMap', [layer]);
        ym.mapType.storage.add('lineage#map', lineageMap);
    
        var map = new ym.Map('map', {
            center: [45, 54],
            zoom: 1,
            type: "lineage#map"
        }, {
            maxZoom: 6,
            minZoom: 1,
            projection: projection
        });
    
        var miniMap = new ym.control.MiniMap();
        miniMap.options.set("zoomOffset", 2); // отличие в зуме минкарты от большой карты
        miniMap.setType('lineage#map');
    
        map.controls.add(miniMap);
    
        map.controls.add(new ym.control.MapTools(['drag', 'magnifier']));
    
        var zoom = new ym.control.ZoomControl({
            customTips: [{
                index: 2,
                value: 'мир'},
            {
                index: 5,
                value: 'земли'}]
        });
        map.controls.add(zoom);
    
        var points = [];
        for (var i = 0; i < 100; i++) {
            var coordinates = [Math.floor(Math.random() * 60) + 20, Math.floor(Math.random() * 60) + 20];
            points[i] = new ym.Placemark(coordinates, {
                hintContent: "point " + i
            }, {
                iconImageHref: "http://wowimg.zamimg.com/images/Mapper/pin-yellow.png",
                iconImageSize: [11, 11]
            });
        }
        var clusterer = new ym.Clusterer();
        clusterer.add(points);
        map.geoObjects.add(clusterer);
    

    Данный пример в корне отличается от двух предыдущих. Начнем с того, что тут мы добавляем слой не через менеджер слоев карты, а через хранилище типов карты. Как видно из названия, нам надо создать тип карты, содержащий в себе наш слой. Который в последствии можно будет задать при инициализации карты type: «lineage#map» и применить к миникарте miniMap.setType('lineage#map').

    В случае с MMORPG и планами зданий нам нет смысла работать со сферическими координатами, поэтому мы используем Декартову систему координат, которую применяем к карте через опцию projection. Теперь точки добавляются не через долготу и широту, а через простые x и y.

    P.S. Чем нарезать тайлы?


    Similar posts

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 14

      0
      При зумировании OpenStreetMap слоя прорисовывается сначала слой Яндекс карт, а потом OSM перерисовывает.
      А еще если использовать OSM его нельзя добавить в список типов карт?
        0
        > При зумировании OpenStreetMap слоя прорисовывается сначала слой Яндекс карт, а потом OSM перерисовывает.
        в примере только OSM слой. Что бы не грузился слой Яндекса добавлено свойство type: null в конструктор карты

        > А еще если использовать OSM его нельзя добавить в список типов карт?
        без проблем. создаете тип карты (как в 3 примере) с OSM слоем, добавляете на карту свой control.ListBox, а в него элементы, которые по клику будут менять тип карты через Map.setType()
          +1
          Пример со списком карт, состоящим из слоев от Яндекс, OSM, Google и Mail.
            0
            Спасибо! То что нужно, только я еще добавил, чтобы заголовок менялся списка при выборе элемента.
              0
              а подскажете как перевести url тайлов кеша sasplanet если для google было так:
              function CustomGetTileUrl(a,b)
              {
              return "http://mykurgan1.narod.ru/cache/gsh/2km/z" + (b+1) + "/"+ Math.floor(a.x/1024) + "/x" + a.x + "/"+ Math.floor(a.y/1024) + "/y" + a.y + ".jpg"; }
            0
            Офигеть как круто!
              0
              Когда зумишь карту Линейки, желтые маркеры почему-то скачат туда-сюда и оказываются не там где ожидалось
                0
                var googleLayer = new ym.Layer('http://mt0.google.com/vt/lyrs=m@176000000&hl=ru&%c', {
                        projection: ym.projection.sphericalMercator,
                        // указываем проекцию слоя Google.Карт
                        tileTransparent: true
                    });

                Убери tileTransparent, и моргания при зуме исчезнут :)
                  +2
                  На всякий случай напомню, что загрузка карт Google вне Google Maps API нарушает их лицензию.
                    0
                    Автор, а что насчет прокладки маршрутов Яши по чужим картам? Будет криво прокладывать, как я понял?
                      0
                      Почему криво? все будет ОК, главное указать у слоя правильную проекцию
                      0
                      Поправте mouseenter — на mouseсenter

                    Only users with full accounts can post comments. Log in, please.