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 图标,我使用事件 mouseenter
和 mouseleave
添加和删除自定义按钮。它看起来不错,我认为这是一个很好且可行的解决方案(这个案例不包括在我的示例中)
我在移动/触摸设备上遇到问题,因为我不知道我可以使用哪些事件来添加 + 删除。
我认为添加事件看起来不错,例如click
、tap
或 touchstart
但我不知道如何在 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 © <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 / 移动设备上的自定义按钮的主要内容,如果未能解决你的问题,请参考以下文章
webpack - 需要('node_modules/leaflet/leaflet.css')