简体   繁体   English

如何扩展 Leaflet 图标 Class 为标记 HTML 添加 data-open 属性?

[英]How to extend Leaflet Icon Class to add data-open attribute to marker HTML?

I'm trying to trigger some functionality based on the click of a marker on a GeoJSON layer in Leaflet. The eventual functionality I'm trying to implement is a flyout, or scroll out type modal populated from the individual feature's JSON attributes.我正在尝试根据在 Leaflet 中的 GeoJSON 层上单击标记来触发某些功能。我尝试实现的最终功能是一个浮出控件,或从单个功能的 JSON 属性填充的滚动类型模态。 Essentially, I'm trying to implement the functionality in this Tutsplus Tutorial with dynamic feature content based on the marker click.本质上,我正在尝试使用基于标记单击的动态功能内容来实现此Tutsplus 教程中的功能。

I THINK I've figured out most of the pieces I need, but I'm struggling with how to add a data attribute, specifically data-open , to the individual marker.我想我已经弄清楚了我需要的大部分内容,但我正在努力解决如何向单个标记添加数据属性,特别是data-open的问题。 Building on an earlier question of mine I've realized it's not enough to just update a DOM element's CSS, but rather my app should be implementing changes based on data attributes to fully get the functionality I want.基于我之前的一个问题,我意识到仅仅更新 DOM 元素的 CSS 是不够的,我的应用程序应该根据数据属性实施更改以完全获得我想要的功能。

From this question I know that this should be done by extending the L.Icon class that Leaflet provides, but the answer is a bit too terse for my current JS skills.这个问题我知道这应该通过扩展 Leaflet 提供的L.Icon class 来完成,但答案对于我目前的 JS 技能来说有点太简洁了。 I apologize for this effectively being a "ELI5" of a previously asked question, but I'm not sure where the options and slug come into function. I think they're implied by the question, rather than the answer I'm citing and being set on the marker itself.我很抱歉这实际上是一个先前提出的问题的“ELI5”,但我不确定optionsslug进入 function 的位置。我认为它们是由问题暗示的,而不是我引用的答案和被设置在标记本身上。

Here's a simplified version of the the click handler on my markers, which grabs and zooms to location, gets feature info, and populates that info to a div.这是我的标记上点击处理程序的简化版本,它抓取并缩放到位置,获取要素信息,并将该信息填充到 div。 The zoom functionality works, as does extracting and placing the feature info, but I'm struggling with how to connect the functionality to trigger the modal and place the div with the feature info over the map.缩放功能有效,提取和放置特征信息也是如此,但我正在努力解决如何连接功能以触发模式并将具有特征信息的 div 放置在 map 上。

function zoomToFeature(e) {
  var latLngs = [e.target.getLatLng()];
  var markerBounds = L.latLngBounds(latLngs);
  var street = e.target.feature.properties.str_addr;
  document.getElementById('street').textContent = street;
  mymap.fitBounds(markerBounds);
  //where the modal trigger should be
  document.getElementById('infoBox').classList.add('is-visible');
}

Here are the event listeners taken from the linked tutorial, which are currently not firing, but I have them working in a standalone implementation:以下是从链接教程中获取的事件侦听器,目前未触发,但我让它们在独立实现中工作:

const openEls = document.querySelectorAll("[data-open]");
const closeEls = document.querySelectorAll("[data-close]");
const isVisible = "is-visible";
//this is the event I want to trigger on marker click
for (const el of openEls) {
  el.addEventListener("click", function() {
    const modalId = this.dataset.open;
    console.log(this);
    document.getElementById(modalId).classList.add(isVisible);
  });
}
for (const el of closeEls) {
  el.addEventListener("click", function() {
 this.parentElement.parentElement.parentElement.classList.remove(isVisible);
  });
}
document.addEventListener("click", e => {
  if (e.target == document.querySelector(".modal.is-visible")) {
    document.querySelector(".modal.is-visible").classList.remove(isVisible);
  }
});

So, where I'm trying to get is that when my markers are clicked, the trigger the modal to appear over the map. So, I think I'm missing connecting the marker click event with the event that triggers the modal.所以,我想要得到的是,当我的标记被点击时,触发模态出现在 map 上。所以,我想我没有将标记点击事件与触发模态的事件连接起来。 I think what's missing is adding the data attribute to the markers, or some way chain the events without the data attributes.我认为缺少的是将data属性添加到标记,或者以某种方式链接没有数据属性的事件。 As there's no direct way to add an attribute to the markers, I try to add slug option on my circle markers:由于没有直接的方法向标记添加属性,我尝试在我的圆形标记上添加 slug 选项:

var circleMarkerOptions = {
    radius: 2,
    weight: 1,
    opacity: 1,
    fillOpacity: 0.8,
    slug: 'open',
}

and If I read the previously asked question's answer correctly, than extending the Icon Class this way should add a data-open attribute.如果我正确阅读了先前提出的问题的答案,那么以这种方式扩展图标 Class 应该添加一个data-open属性。

L.Icon.DataMarkup = L.Icon.extend({

    _setIconStyles: function(img, name) {
        L.Icon.prototype._setIconStyles.call(this, img, name);

        if (options.slug) {
            img.dataset.slug = options.slug;
        }
    }

});

A stripped down version of my code is here (thanks @ghybs).我的代码的精简版本在这里(感谢@ghybs)。 My full implementation pulls the markers from a PostGIS table.我的完整实现从 PostGIS 表中提取标记。 It's a bit hard to see in the Plunker, but this code adds my class to my modal, but doesn't trigger the functionality.在 Plunker 中很难看到,但这段代码将我的 class 添加到我的模式中,但不会触发该功能。 It does trigger the visibility if the class is manually updated to modal.is-visible , but the current implementation which renders modal is-visbile doesn't, which I think is because the CSS is interpreted on page load(?) and not in response to the update via the dev tools, while the concatenated css class matches extactly(?).如果将 class 手动更新为modal.is-visible ,它确实会触发可见性,但呈现modal is-visbile不会,我认为这是因为 CSS 是在页面加载时解释的(?)而不是在通过开发工具响应更新,而串联的 css class 完全匹配(?)。 When I do trigger the modal via the dev tools, the close modal listeners don't seem to work, so I'm also missing that piece of the puzzle.当我确实通过开发工具触发模态时,关闭模态侦听器似乎不起作用,所以我也遗漏了那块拼图。

So, it's a work-around to setting the data attribute, but I realized I was shoe-horning a solution where it wasn't needed.所以,这是设置数据属性的一种变通方法,但我意识到我是在用鞋拔一个不需要的解决方案。 Assuming someone ends up with the same mental block.假设有人最终遇到了同样的心理障碍。 Appropriate listeners on the modal close button and another function passed to the existing marker click listener produce the desired functionality.模式关闭按钮上的适当侦听器和传递给现有标记单击侦听器的另一个 function 会产生所需的功能。

const closeM = document.querySelector(".close-modal");
closeM.addEventListener("click", closeMe);
var modal = document.getElementById('infoBox');

and

function modalAction(){
    modal.style.display = 'block';
}
function closeMe(){
    modal.style.display = 'none';
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM