Leaflet / LayersControl / 移动设备上的自定义按钮

Posted

技术标签:

【中文标题】Leaflet / LayersControl / 移动设备上的自定义按钮【英文标题】:Leaflet / LayersControl / Custom buttons on mobile device 【发布时间】:2021-11-18 15:40:19 【问题描述】:

我是 JS / jQuery 初学者,也许很愚蠢,但我在移动设备上向 Leaflet LayersControl 添加 + 删除自定义按钮时遇到问题。

项目描述: 我有多个图层的地图,我需要添加两个按钮来选中/取消选中所有复选框(它在示例中有效)。

这是我的示例,需要在浏览器中打开触摸模拟: https://jsfiddle.net/lukassliacky/n2ep6yg0/42/(在 Firefox 上创建和测试)。

正如我所说,我还是 JS 初学者,对我来说似乎是使用 after 添加自定义 html 的最简单的解决方案,但我对触摸设备上的事件有疑问。

在桌面(非触摸)上看起来很简单:右上角是折叠的 LayerControl 图标,我使用事件 mouseentermouseleave 添加和删除自定义按钮。它看起来不错,我认为这是一个很好且可行的解决方案(这个案例不包括在我的示例中)

我在移动/触摸设备上遇到问题,因为我不知道我可以使用哪些事件来添加 + 删除。

我认为添加事件看起来不错,例如clicktaptouchstart 但我不知道如何在 LayerControl 展开时删除按钮,它将被折叠。 它对我来说很复杂,因为我需要从地图中排除一些 div(带有复选框的图层控制 - 当我要单击复选框时,我的自定义按钮将被删除)

  $('#main-map:not(leaflet-control-layers-expanded > div).click(function() 
    $('.leaflet-custom-buttons').remove()

  )
  $('.leaflet-control').click(function(e) 
    e.stopPropagation();
  );

当我展开 LayersControl(带有按钮)并且当我点击 Pin 标记时,按钮被移除并且 LayerControl 仍然被展开(它不是很好)。在这种情况下,LayersControl 在单击不同对象作为 Pin Marker 后折叠。

请问,您能帮我使用正确的事件来添加/删除移动设备上的自定义按钮吗?当然,也许是我的方法不对,需要重写我的代码。

谢谢

【问题讨论】:

如果我理解正确,您希望移动设备上的此 LayersControl 与桌面设备上的行为方式相同,即消失。我认为你不应该改变它,它符合用户体验规则,这就是它应该在移动设备上做的事情。如果你想在移动设备上隐藏一些东西,你也可以使用下面的 css 条目:@media (hover: hover) a: hover background: yellow; 不幸的是,它在 IE 中不起作用,但谁会在乎;) 嗨@GrzegorzT。谢谢您的回答。我的英语不是我的母语,也许我描述我的“问题”还不够。当我在移动设备上点击 LayersControl 图标时,我需要使用复选框和我的自定义按钮打开 div(这部分效果很好)。当我在此 LayersControl div 之外单击时,我需要对 LayersControl div 和自定义按钮具有相同的行为。当前状态:当我单击除 Pin Markers 之外的地图时,工作正常,但是当我直接单击 Pin Marker 时,LayersControl 仍然打开并且我的自定义按钮被删除 - 我需要相同的行为。谢谢。 我尝试了第二轮谷歌搜索,我发现自定义按钮可能更好的方法:embed.plnkr.co/Je7c0m 我正在尝试在我的项目中实现这个示例,我会在这里写下结果。 【参考方案1】:

好吧,我尝试了不同的方法,似乎是正确的方法。

使用自定义按钮的更新示例在这里:https://jsfiddle.net/lukassliacky/n2ep6yg0/57/

    var cities = L.layerGroup();
    var secondLayer = L.layerGroup();
    var thirdLayer = L.layerGroup();
  

    L.marker([39.61, -105.02]).bindPopup('This is Littleton, CO.').addTo(cities),
    L.marker([39.24, -104.39]).bindPopup('This is Denver, CO.').addTo(cities),
    L.marker([39.33, -103.2]).bindPopup('This is Aurora, CO.').addTo(cities),
    L.marker([39.17, -105.43]).bindPopup('This is Golden, CO.').addTo(cities);

    L.marker([39.51, -105.52]).bindPopup('This is Littleton, CO.').addTo(secondLayer),
    L.marker([39.34, -104.29]).bindPopup('This is Denver, CO.').addTo(secondLayer),
    L.marker([39.13, -104.3]).bindPopup('This is Aurora, CO.').addTo(secondLayer),
    L.marker([39.97, -105.63]).bindPopup('This is Golden, CO.').addTo(secondLayer);
  
  L.marker([39.21, -105.52]).bindPopup('This is Littleton, CO.').addTo(thirdLayer),
    L.marker([39.34, -104.09]).bindPopup('This is Denver, CO.').addTo(thirdLayer),
    L.marker([39.73, -104.28]).bindPopup('This is Aurora, CO.').addTo(thirdLayer),
    L.marker([39.17, -105.53]).bindPopup('This is Golden, CO.').addTo(thirdLayer);

    var mbAttr = 'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, ' +
            'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
        mbUrl = 'https://api.mapbox.com/styles/v1/id/tiles/z/x/y?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw';

    var grayscale   = L.tileLayer(mbUrl, id: 'mapbox/light-v9', tileSize: 512, zoomOffset: -1, attribution: mbAttr),
        streets  = L.tileLayer(mbUrl, id: 'mapbox/streets-v11', tileSize: 512, zoomOffset: -1, attribution: mbAttr);

    var map = L.map('main-map', 
        center: [39.73, -104.99],
        zoom: 7,
        layers: [grayscale, cities, secondLayer, thirdLayer]
    );

    var baseLayers = 
/*      "Grayscale": grayscale,
        "Streets": streets */
    ;

    var overlays = 
        "Cities": cities,
    "SecondLayer": secondLayer,
    "ThirdLayer": thirdLayer,
    
    ;


L.Control.Custom = L.Control.Layers.extend(
    onAdd: function () 
            this._initLayout();
            this._addCheckButton();
            this._addClearButton();
            this._update();
            return this._container;
        ,
        _addCheckButton: function () 
        var elements = this._container.getElementsByClassName('leaflet-control-layers-list');
        var button = L.DomUtil.create('button', 'btn btn-primary rounded-0 my-1 me-1 btn-xs leaflet-btn-check-all', elements[0]);
        button.textContent = 'Check All';
        L.DomEvent.on(button, 'click', function(e)
            L.DomEvent.stop(e);

            // fire this function (check all)
            $('.leaflet-control input[type="checkbox"]').trigger('click').prop('checked', true);
        , this);
        ,
        _addClearButton: function () 
        var elements = this._container.getElementsByClassName('leaflet-control-layers-list');
        var button = L.DomUtil.create('button', 'btn btn-primary rounded-0 my-1 btn-xs w-50 leaflet-btn-check-all', elements[0]);
        button.textContent = 'Clear All';
        L.DomEvent.on(button, 'click', function(e)
            L.DomEvent.stop(e);

            // fire this function (uncheck all)
            $('.leaflet-control input[type="checkbox"]').trigger('click').prop('checked', false);
        , this);
        
    );
    
    new L.Control.Custom(
        baseLayers, 
        overlays,
        collapsed:true).addTo(map);   
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-locatecontrol/0.74.0/L.Control.Locate.min.js"></script>
<link href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" rel="stylesheet"/>
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>

    <style>
        html, body 
            height: 100%;
            margin: 0;
        
        #main-map   
            width: 100%;
            height: 500px;
        
    </style>    
</head>
<body>

<div id='main-map'></div>

我的解决方案基于https://embed.plnkr.co/Je7c0m/,非常感谢作者。 Grzegorz T. 也感谢您的支持。

【讨论】:

以上是关于Leaflet / LayersControl / 移动设备上的自定义按钮的主要内容,如果未能解决你的问题,请参考以下文章

leaflet加载天地图

webpack - 需要('node_modules/leaflet/leaflet.css')

leaflet学习一 入门

在反应传单上使用Leaflet插件

leaflet+esri-leaflet+heatmap实现热力图

Leaflet绘制热力图