传单popup.update()调整大小的解决方案-每次都重新创建弹出窗口,无法单击嵌入式URL

时间:2018-08-07 17:51:45

标签: javascript popup leaflet

我应用了@ghybs提供的popup.update()代码段,可以很好地调整弹出窗口使其适合地图框架,如您在此处看到的代码所示:

start

问题是我在每个弹出窗口的缩略图中都嵌入了一个URL。当我单击缩略图时,光标指示应该可以单击“单击”,但它不会执行任何操作。右键单击缩略图后,可以在新标签页中打开网址。网址在那里,只是无法按我想要的方式工作。我和一个朋友看着代码,我们确定正在不断重新创建javascript弹出窗口。他建议可能是更新电话,但不确定。如果有一种方法可以阻止javascript不断重新创建弹出窗口,那么这可能会解决问题。

他还指出,当他停止运行JavaScript时,只有在应该占据整个缩略图(通常为250px)的情况下,该URL才可在缩略图的下半部分(特别是14px高)上单击。

在更新后立即检查console.log(popup)时,它陷入了无限循环。我猜这是问题的核心。有没有办法在更新弹出窗口大小后停止更新?我希望这样做可以释放嵌入的URL,以便可以单击,但我也希望链接的高度与整个缩略图匹配。

作为参考,我正在从geojson文件中提取点并将相同的方法应用于每个点,就像这样:

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);

1 个答案:

答案 0 :(得分:2)

欢迎您!

哼哼,当您将弹出内容指定为包含<img>的HTML字符串时,看起来given workaround确实创建了一个无限循环。发生的情况是,当图像完成加载后,popup.update()使用HTML字符串重置Popup内容,因此重新创建<img>元素,该元素会发出新的"load"事件,即使现在它来自浏览器缓存。然后,侦听器再次执行popup.update(),依此类推。

演示(打开Web控制台以查看无限循环日志记录“来自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/leaflet@1.3.3/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" />
<script src="https://unpkg.com/leaflet@1.3.3/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/leaflet@1.3.3/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" />
<script src="https://unpkg.com/leaflet@1.3.3/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字符串中包含任意数量的图像,并且可以同时打开多个Popup的情况,现在可以泛化解决方案,我们可以想象:

  1. "popupopen"和每个图像"load"事件中,检查所有弹出图像是否具有非零的naturalWidth,否则进行更新。
  2. 在每个图像上存储对Popup的引用,这样我们就不必读取map._popup(仅引用最后一个打开的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/leaflet@1.3.3/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" />
<script src="https://unpkg.com/leaflet@1.3.3/dist/leaflet-src.js" integrity="sha512-GosS1/T5Q7ZMS2cvsPm9klzqijS+dUz8zgSLnyP1iMRu6q360mvgZ4d1DmMRP2TDEEyCT6C16aB7Vj1yhGT1LA==" crossorigin=""></script>

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

然后,我们甚至可以通过尝试update as soon as the images have their naturalWidth而不是等待它们的"load"事件来进一步改进此解决方案,以便即使在浏览器仍在获取事件时,也会更新Popup的大小和位置