Клуб API Карт

Как удалить все слои на карте?

Алексей
14 ноября 2010, 23:45

Перерыл весь api и клуб Яндекс.Карт - не могу найти/понять как удалить все слои на карте?

Например создаю слой map.addLayer(ml, '#Layer1');

если сразу (следующей строкой) попытаться вызвать map.removeLayer(ml, '#Layer1') , то удаляется.

А как мне (например по какому то событию) получить список всех пользовательских слоев, которые есть на карте и затем их все удалить?

20 комментариев
Подписаться на комментарии к посту
есть одна методика, которая работает всегда и везде.

var oldref=map.addLayer;
var mapLayers={};
map.addLayer = function(val,name){
  mapLayers[name]=ml;
  oldref(val,name);
}

map.removeAllUserLayers = function(){
 $.each(mapLayers,function(i,j){
  map.removeLayer(j,i);
 });
 mapLayers={};
}

Один смысл этого кода - запоминай чего ты добавляешь, второй смысл - хакни малек конечный апи, чтобы делать это(запоминать) прозрачно.

Второе - не есть гут. Но метод получил распространения благодаря недоработкам Gv3
thekashey вам правильно подсказывает: нужно сохранять то, что добавляете, а потом все разом удалять.

Я бы создал простенький менеджер слоев и работал через него:

function LayersManager (map) {
    YMaps.Group.call(this);

    this.map = map;

    YMaps.Events.observe(this, this.Events.Add, function (group, layer) {
        this.add(layer);
        this.map.addLayer(layer);
    }, this);

    YMaps.Events.observe(this, this.Events.Remove, function (group, layer) {
        this.remove(layer);
        this.map.removeLayer(layer);
    }, this);
}
YMaps.Utils.extend(LayersManager, YMaps.Group);

Использовать его просто.

var layers = new LayersManager(map);
layers.add(layer1);
layers.add(layer2);

А потом удаляете все разом:

layers.removeAll()
Спасибо вам обоим!
rodlex,
попробовал внедрить этот код, но он выдает мне ошибку "Stack overflow at line: 11"
Не пойму, в чем дело?
У меня порядок действий такой: 
window.onload = function () {
// здесь идет инициализация карты, а затем
showMag ('Rzn');
}
function showMag ($tip){
// эта функция загружает слои активных областей на карту.
// эта функция вызывется при инициализации, а затем, когда пользователь менят тип данных, которые хочет увидеть на карте
}

В чем может быть проблема?
Кстати, пришел к выводу что активные области - это хорошо, но скрипт, который готовит тайлы реально вешает сервер, на виртуальном хостинге переполняется память. Поэтому подумываю использовать активные области в масштабах 1-11, а затем все же попробовать использовать этот метод: http://clubs.ya.ru/mapsapi/replies.xml?item_no=8089#overlays-4
Кстати, кто автор скрипта http://probki.avtoradio.ru/vardata/include/yandexmap1_1.js - не в курсе? Можно взять его за основу, и не будет потом проблем с авторскими правами?
А можете дать ссылку на страничку? Так сложно сказать где ошибка.

Скрипт для авторадио писал я.
Работу скрипта без дополнительного обвеса можно здесь: http://hevil.narod2.ru/autoclubs/index.html
Правда, выложена не последняя версия; если хотите - обновлю.

Проблем с авторскими правами не будет, можете смело брать ;)
rodlex,
обновите пожалуйста! Я сейчас болею, но как смогу, выложу ссылку на свою карту.
Обновил. Выздоравливайте и снова в бой ;)
rodlex,
здравствуйте!
Разместил свою карту здесь:
http://tovarydetyam.temeshov.ru/#lat=55.72950603552662&lng=37.704338002949974&z=12&mt=map 

При загрузке (при добавлении слоя на карту, используя Ваш менеджер слоев) происходит ошибка.
В ie всплывает окно Stack overflow at line: 11
Во всех IE?
После каких действий?
Да, в всех IE? а в других браузерах просто прерывается работа скрипта и все, без всяких сообщений.
В момент добавления слоя, т.е. layers.add(ml);

Я что-то накрутил наверное, но теперь выдает Stack overflow at line: 174
Больше пока ничего менять не буду.
http://tovarydetyam.temeshov.ru/Где_продают#lat=55.589420216102305&lng=85.87904350832106&z=3&mt=map
Виною всему LayersManager. Происходит рекурсивное добавление слоя, и почему я так, написал?)

Верный вариант (по событиям Add и Remove не нужно добавлять и удалять слой из группы):

function LayersManager (map) {
    YMaps.Group.call(this);

    YMaps.Events.observe(this, this.Events.Add, function (group, layer) {
        map.addLayer(layer);
    }, this);

    YMaps.Events.observe(this, this.Events.Remove, function (group, layer) {
        map.removeLayer(layer);
    }, this);
}                                                                                                                                                                                 
YMaps.Utils.extend(LayersManager, YMaps.Group);

Извините, в следующий раз, буду внимательнее.
rodlex,
спасибо, что помогаете!
Код исправил - ошибка исчезла. Но при вызове layers.removeAll(); слои не удаляются. А как Вы помните задача стояла удалить все слои, которые размещены на карте.
Сейчас проверил, LayersManager удаляет все слои.

Тестировал вот так:

YMaps.jQuery(function () {
    var map = new YMaps.Map(YMaps.jQuery("#YMapsID")[0]);
    map.setCenter(new YMaps.GeoPoint(86.09014,55.35), 5);
                                                                                                                                                                                  
    var layers = new LayersManager(map);
    layers.add("sat");
    layers.add("skl");

    layers.removeAll();
})
rodlex,
так действительно удаляет.

Может я не совсем понятно объяснил ситуацию... напишу еще раз.


У меня есть функция ShowMag, которая вызывается при переключении типа магазинов (розничные/оптовые/ и т.д.). Эта функция показывает на карте необходимый тип магазинов (добавляет новый слой), но прежде чем она покажет этот тип, мне нужно удалить все другие слои, если они есть.


Получается что LayersManager работает только в рамках этой функции. А нужно чтобы он был более глобальным что-ли. Т.е. чтобы код выглядел примерно так:


YMaps.jQuery(function () {
var map = new YMaps.Map(YMaps.jQuery("#YMapsID")[0]);
map.setCenter(new YMaps.GeoPoint(86.09014,55.35), 5);
showMag('roznitsa'); // при инициализации карты показываем розничные магазины
})

ShowMag(magType){
var layers = new LayersManager(map);
layers.removeAll();  // сначала удаляем все слои, которые есть на карте
layers.add("sat"); // добавляем новый слой (необходимый тип магазинов)
}

далее в html где-то есть onChange="showMag(this.value)" // показать новый тип магазинов



Или есть какой-нибудь другой способ полностью очистить карту? Может её вообще удалять а потом заново инициализировать? На нашей старой карте Google мы вообще делали очистку через перезагрузку страницы. Но мне кажется что это не совсем хорошее решение.
Алексей,
я в начале топика я описал совершенно железобетоную методику.
В принципе именно через такой код на техже гугл картах v3 создавали аналоги функции removeAllOverlays которая была в v2, да пропала :)

но честное слово - вариант от Саши тоже полностью работоспособен, надо просто вынести обьявление(но не инициализацию) layers за пределы функции, чтобы он, и как переменая и как набор функций, стал просто навсего доступен всем
thekashey, спасибо за помощь!
Честно говоря Ваш код не стал использовать из-за второго аргумента "что не есть гуд" :)
Но чем больше пытался понять почему не работает этот пресловутый LayersManager Саши, тем больше склонялся использовать Ваш код. Что касается "надо просто вынести обьявление(но не инициализацию) layers за пределы функции" - у меня вроде так и было...

Прочитал в здесь про всякие методы над классом Group. Воспользовался length() чтобы посчитать количество объектов в группе, сразу после добавления нескольких слоев написал мне правильное ко-во объектов (например 5). А вот когда я попытался создать отдельную функцию 


function clearMap() {
var layers = new LayersManager(map);
alert(layers.length()); // выводит 0, хотя до этого вызывалась функция добавления слоев
layers.removeAll();
}

в ней алерт выдает 0.
Соответственно думаю что для решения проблемы осталось разобраться что у меня не так, в плане почему LayersManager не получается глобальным?
Если не затруднит, код можно посмотреть здесь: http://tovarydetyam.temeshov.ru
Глобальным сделать несложно:

var layers; // Глобальная переменная
window.onload = function () {


А вот в других местах сотрите ключевое слово "var" перед layers, чтобы локальные переменные не перекрывали глобальные.
Уфффф, получилось!
Наконец то все заработало! Может кто-то посчитает что эта "проблема" родилась на пустом месте, но надеюсь кому то вся эта переписка может потом пригодится.
Еще раз большое человеческое спасибо и Кощею и Саше за то, что досконально помогают разобраться с проблемами пользователей. Зато я более досконально ознакомился с классом Group и теперь понимаю как он работает! :)

не поверите - но я тоже :)