Leaflet popup.update () Решение по изменению размера - воссоздание всплывающего окна каждый раз, невозможно щелкнуть встроенный URL

1

Я применил фрагмент кода popup.update(), предоставленный @ghybs, который очень хорошо работает, чтобы настроить всплывающее окно, чтобы оно соответствовало рамке карты, так как здесь вы можете увидеть код:

document.querySelector(".leaflet-popup-pane").addEventListener("load", function (event) {
  var tagName = event.target.tagName,
      popup = map._popup;
  console.log("got load event from " + tagName);
  if (tagName === "IMG" && popup) {
    popup.update();
  }
}, true);

Проблема в том, что я встроил URL-адрес в миниатюру для каждого всплывающего окна. Когда я нажимаю на миниатюру, курсор указывает, что "щелчок" должен быть возможен, но он ничего не делает. Когда я нажму правой кнопкой мыши на миниатюре, я могу открыть URL-адрес на новой вкладке. Так что URL-адрес есть, просто не работает так, как я этого хочу. Мы с другом посмотрели код, и мы определили, что всплывающее окно javascript постоянно воссоздается. Он предположил, что это может быть звонок по обновлению, но не был уверен. Если есть способ остановить javascript от постоянного воссоздания всплывающего окна, это может решить проблему.

Он также отметил, что, когда он останавливает запуск javascript, URL-адрес доступен только в нижней части миниатюры (в частности, 14 пикселей в высоту), когда он должен занимать весь миниатюру (обычно 250 пикселей).

Когда я проверил для console.log(popup) сразу после обновления, он застревает в бесконечном цикле. Я предполагаю, что это суть проблемы. Есть ли способ остановить обновление после обновления всплывающего окна? Я надеюсь, что это освободит внедренный URL-адрес, чтобы его можно было щелкнуть, но мне также хотелось бы, чтобы высота ссылки соответствовала всему миниатюре.

Для справки, я извлекаю точки из файла geojson и применяя один и тот же метод к каждой точке, например:

var clusters = L.markerClusterGroup({maxClusterRadius:75});
var getjson = $.getJSON("map-v2.geojson",function(data){
  var bev = L.geoJson(data,{
    pointToLayer: function(feature,latlng){
      var marker = L.marker(latlng, { tags: feature.properties.Genres.concat(feature.properties.Creator)});
      marker.bindPopup('<p align=center>' + '<strong>Title: </strong>' + feature.properties.Title + '<br/><a href="' + feature.properties.Image_Bank_URL + '" target="_blank"><img src="' + feature.properties.Thumbnail_URL + '"/></a><br/>' + '<strong>Date: </strong>' + feature.properties.Date + '<br/>' + '<strong>Creator: </strong>' + feature.properties.Creator + feature.properties.Genre, {minWidth : 250});
      return marker;
    }
  });
  clusters.addLayer(bev);
  map.addLayer(clusters);
});
Теги:
leaflet
popup

1 ответ

1
Лучший ответ

Добро пожаловать в SO!

Действительно, похоже, что данное обходное решение создает бесконечный цикл, когда вы указываете всплывающее содержимое как строку HTML, содержащую <img>. Случается, что когда изображение завершает загрузку, popup.update() сбрасывает содержимое всплывающей popup.update() с помощью строки HTML, поэтому повторно создает элемент <img>, который испускает новое событие "load", даже если теперь оно происходит из кеш браузера. Затем слушатель снова выполняет popup.update() и т.д.

Демонстрация (откройте свою веб-консоль, чтобы увидеть запись inifinite loop logging), получившее событие загрузки от IMG):

var map = L.map('map').setView([48.86, 2.35], 11);

// Modify the cache busting value to force browser fetching from network.
var imgSrc = 'https://a.tile.openstreetmap.org/0/0/0.png?bust=1';
var popupContent =
  '<a href="https://a.tile.openstreetmap.org/0/0/0.png" target="_blank">' +
  '<img src="' + imgSrc + '"/></a>';

L.marker([48.86, 2.35]).addTo(map).bindPopup(popupContent);

document.querySelector(".leaflet-popup-pane").addEventListener("load", function(event) {
  var tagName = event.target.tagName,
    popup = map._popup;
  console.log("got load event from " + tagName);
  if (tagName === "IMG" && popup) {
    popup.update();
  }
}, true);

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
html,
body,
#map {
  height: 100%;
  margin: 0;
}
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" />
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-GosS1/T5Q7ZMS2cvsPm9klzqijS+dUz8zgSLnyP1iMRu6q360mvgZ4d1DmMRP2TDEEyCT6C16aB7Vj1yhGT1LA==" crossorigin=""></script>

<div id="map"></div>

В вашем случае, если вы уверены, что в любой момент времени будет открыто только 1 всплывающее окно, и что он включает только один <img>, вы можете просто установить флаг сначала "load" событие на этом всплывающем окне, чтобы для предотвращения инфинитной циклы:

var map = L.map('map').setView([48.86, 2.35], 11);

// Modify the cache busting value to force browser fetching from network.
var imgSrc = 'https://a.tile.openstreetmap.org/0/0/0.png?bust=2';
var popupContent =
  '<a href="https://a.tile.openstreetmap.org/0/0/0.png" target="_blank">' +
  '<img src="' + imgSrc + '"/></a>';

L.marker([48.86, 2.35]).addTo(map).bindPopup(popupContent);

document.querySelector(".leaflet-popup-pane").addEventListener("load", function(event) {
  var tagName = event.target.tagName,
    popup = map._popup;
  console.log("got load event from " + tagName);
  // Also check if flag is already set.
  if (tagName === "IMG" && popup && !popup._updated) {
    popup._updated = true; // Set flag to prevent looping.
    popup.update();
  }
}, true);

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
html,
body,
#map {
  height: 100%;
  margin: 0;
}
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" />
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-GosS1/T5Q7ZMS2cvsPm9klzqijS+dUz8zgSLnyP1iMRu6q360mvgZ4d1DmMRP2TDEEyCT6C16aB7Vj1yhGT1LA==" crossorigin=""></script>

<div id="map"></div>

(обратите внимание, что фрагменты кода SO, по-видимому, препятствуют <a href> ссылок, поэтому здесь находится Plunk, чтобы проверить, что ссылка открыта нормально: https://next.plnkr.co/edit/ore09Yxmm6DVmJGc)

Теперь, чтобы обобщить решение для случая, когда произвольное количество изображений содержится в строке HTML, и когда несколько всплывающих окон могут открываться одновременно, мы могли бы представить себе:

  1. На "popupopen" и каждое изображение "load" события, проверьте все Всплывающие изображения имеют ненулевой naturalWidth, обновлять иначе.
  2. Храните ссылку на всплывающее окно на каждом изображении, так что нам не нужно прибегать к чтению map._popup (который ссылается только на последний открытый всплывающий).

var map = L.map('map', {
  closePopupOnClick: false
}).setView([48.86, 2.35], 11);

// Modify the cache busting value to force browser fetching from network.
var imgSrc1 = 'https://a.tile.openstreetmap.org/0/0/0.png?bust=3';
var imgSrc2 = 'https://a.tile.openstreetmap.org/11/1037/704.png?bust=3';
var popupContent =
  '<a href="' + imgSrc1 + '" target="_blank">' +
  '<img src="' + imgSrc1 + '"/></a>' +
  '<a href="' + imgSrc2 + '" target="_blank">' +
  '<img src="' + imgSrc2 + '"/></a>';

L.marker([48.86, 2.35]).addTo(map).bindPopup(popupContent, {
  autoClose: false
}).on('click', function() {
  // Open another Popup after this one.
  m2.openPopup();
});

var m2 = L.marker([48.86, 2.32]).bindPopup('Second Popup', {
  autoClose: false
}).addTo(map);

// Prepare the Popup when it opens.
map.on('popupopen', function(event) {
  var popup = event.popup;
  popup._imgAllSized = popupImgAllSized(popup);
});

document.querySelector(".leaflet-popup-pane").addEventListener("load", function(event) {
  var target = event.target,
    tagName = target.tagName,
    popup = target._popup;
  console.log("got load event from " + tagName);
  // Also check the Popup "_imgAllSized" flag.
  if (tagName === "IMG" && popup && !popup._imgAllSized) {
    console.log('updated');
    // Update the flag, in case all images have finished loading.
    popup.update();
    popup._imgAllSized = popupImgAllSized(popup);
  }
}, true);

function popupImgAllSized(popup) {
  // Get the HTMLElement holding the Popup content.
  var container = popup._contentNode;
  var imgs = container.querySelectorAll('img');
  var imgAllSized = true;
  for (var i = 0; i < imgs.length; i += 1) {
    // Store reference to popup in <img>
    imgs[i]._popup = popup;
    // Check if the image has unknown size.
    if (!imgs[i].naturalWidth) {
      imgAllSized = false;
    }
  }
  console.log(imgAllSized);
  return imgAllSized;
}

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
html,
body,
#map {
  height: 100%;
  margin: 0;
}
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" />
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-GosS1/T5Q7ZMS2cvsPm9klzqijS+dUz8zgSLnyP1iMRu6q360mvgZ4d1DmMRP2TDEEyCT6C16aB7Vj1yhGT1LA==" crossorigin=""></script>

<div id="map"></div>

Затем мы могли бы еще больше улучшить это решение, пытаясь обновить, как только у изображений будет свой naturalWidth, вместо того, чтобы ждать своего события "load", так что даже пока браузер все еще их извлекает, размер и положение Popup обновляются.

  • 0
    Хорошая новость заключается в том, что это решение нарушает цикл, что позволяет получить доступ к встроенному URL. Плохая новость заключается в том, что исправление больше не регулирует высоту, как предполагалось (оно настраивается на полпути вверх во всплывающем окне). Я проверил журнал консоли (я добавил один после popup.update), и кажется, что когда я щелкаю точку в первый раз, EventListener загружает событие, проверяет, обновлено ли, обновляет, загружает событие снова, затем флаг останавливает обновление. Итак, он проходит правильные шаги, но по какой-то причине первое обновление не подстраивается под некоторые. embed.plnkr.co/Ee8QYy
  • 0
    Не уверен, что именно вы имеете в виду? Ваш Plunker работает как положено для меня в Chrome и Firefox.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню