我尝试了这几种方法,但未能使其正常工作。我想在多个时区内将时钟放在地图的顶部。我有一个用于创建时钟的javascript,我将时钟放在div
元素中。
以下是我的尝试:
0,0
坐标创建一个点。containerPointToLatLng
获取地图顶部的纬度值。LatLng
,为时区创建long。LatLng
转换为Point,然后从此处将div元素与x,y
对齐。我首先渲染页面然后在body调整大小时执行逻辑。但是,如果我更改浏览器窗口的大小,则时钟位置不正确。
有什么建议吗?
答案 0 :(得分:13)
要回答OP的精确问题,即如何在调整浏览器窗口大小时重新定位时钟(因此地图容器尺寸可能已经改变),可能只需重新计算地图上的时钟位置&# 39; s "resize"
事件。
但是,目前尚不清楚OP是将时钟作为地图容器的子项还是页面DOM树上的其他位置。
将它作为地图的子项放置可能要容易得多,因此它的位置始终相对于地图容器。
如果我理解正确的原始期望结果,OP希望在特定地理位置(根据评论的情况下,多伦多市[UTC -5])覆盖时钟(或任何信息)。< / p>
但是,信息容器不应位于底图固定位置,即不在精确的地理协调点(如标记或弹出窗口),而是在地图容器的顶部,类似于控件(因此iH8的原始答案)。
除了它不应该在地图容器中完全固定,而是与城市(或任何指定的地理坐标)水平移动。因此,OP对iH8的回答发表了评论。
因此它听起来类似于that site,除了交互式(可导航)地图和&#34; UTC-5&#34;标题被时钟(或任何信息,因此HTML容器应该这样做)替换为水平跟随多伦多。
换句话说,时钟应位于特定的垂直线,即经度/子午线。
不幸的是,即使问题发布后的2年半,仍然没有提供此类功能的Leaflet插件(至少在Leaflet plugins page内)。
话虽如此,并且鉴于用户可能能够高度放大到城市(OP没有指定最大缩放级别)这一事实,可能不是一个非常好的用户体验,该时钟水平遵循精确经度:例如,它可以跟踪多伦多质心/市政厅/任何特定的地方,当用户在另一个城区放大时,时钟不再可见,而他/她仍在观看多伦多市的一部分......
要扩展该用例,时钟应该很可能在它应用的任何区域都可见,即一旦地图视图端口与相关的时区相交。
OP未详细说明的另一点是,在地图视口中可以看到不同时区的地点时该怎么办?在above mentioned site中,我们每个可见时区一个标题,这似乎是我们可以获得的最完整的信息。
但是由于Leaflet允许缩小到0级,整个世界(即基本上24个时区/ actually 39 according to Wikipedia,不包括夏令时的潜在影响 - DST)用256像素宽度表示如果每个时钟必须与其相关的时区垂直对齐,那么几乎没有空间适合所有这些时钟。
现在让我们假设我们不关心时钟是否重叠。
但OP可能希望仅针对特定地点显示时钟,而不是针对整个世界。 OP甚至没有说时钟会有所不同(我们可以为同一时区的城市设置时钟,即使将这些时钟放在他们的城市旁边可能会更有趣 - 即使与他们的纬度相同,所以它也是如此更容易发现时钟所关联的城市,例如同一个子午线上的2个城市;但在这种情况下,使用L.divIcon
的标记就足够了。
因此,自定义案例不会考虑官方时区,而是开发人员指定的区域。
所以我们忘记了纬度,并尝试将一个时钟垂直对准该区域,只要它与地图视口相交。
因此,听起来通用的解决方案是让应用程序开发人员指定一个HTML元素数组,每个元素都与一系列经度相关联(也可以是一个区域/多边形)。
时区用例将是一个特殊情况,其中指定区域只是来自时区的区域。
然后,当且仅当其相关区域与视口相交时,每个元素都应该是可见的(因此,当纬度范围不在视图范围内时,我们会引入隐藏它的可能性。)
至于定位,让我们选择:
<强> HTML:强>
<div id="map"></div>
<div id="clockToronto" class="clock leaflet-control">Clock here for Toronto</div>
<div id="clockBurlington" class="clock leaflet-control">Clock here for Burlington</div>
<强> CSS:强>
.clock {
width: 150px;
text-align: center;
position: absolute;
border: 1px solid black;
}
#clockToronto {
background-color: yellow;
}
#clockBurlington {
background-color: orange;
}
<强> JavaScript的:强>
var map = L.map("map").setView([43.7, -79.4], 10);
// Application specific.
var clockTorontoElement = L.DomUtil.get("clockToronto"),
clockBurlingtonElement = L.DomUtil.get("clockBurlington"),
zones = [
{
element: clockTorontoElement, // Using the HTML Element for now.
width: parseInt(window.getComputedStyle(clockTorontoElement, null).getPropertyValue("width"), 10),
area: L.latLngBounds([43.58, -79.64], [43.86, -79.10]) // Using L.latLngBounds for now.
},
{
element: clockBurlingtonElement, // Using the HTML Element for now.
width: parseInt(window.getComputedStyle(clockBurlingtonElement, null).getPropertyValue("width"), 10),
area: L.latLngBounds([43.28, -79.96], [43.48, -79.71]) // Using L.latLngBounds for now.
}
];
// Initialization
var controlsContainer = map._container.getElementsByClassName("leaflet-control-container")[0],
firstCorner = controlsContainer.firstChild,
mapContainerWidth;
map.on("resize", setMapContainerWidth);
setMapContainerWidth();
// Applying the zones.
for (var i = 0; i < zones.length; i += 1) {
setZone(zones[i]);
}
function setZone(zoneData) {
// Visualize the area.
L.rectangle(zoneData.area).addTo(map);
console.log("width: " + zoneData.width);
controlsContainer.insertBefore(zoneData.element, firstCorner);
map.on("move resize", function () {
updateZone(zoneData);
});
updateZone(zoneData);
}
function updateZone(zoneData) {
var mapBounds = map.getBounds(),
zoneArea = zoneData.area,
style = zoneData.element.style;
if (mapBounds.intersects(zoneArea)) {
style.display = "block";
var hcenterLng = getIntersectionHorizontalCenter(mapBounds, zoneArea),
hcenter = isNaN(hcenterLng) ? 0 : map.latLngToContainerPoint([0, hcenterLng]).x;
// Update Element position.
// Could be refined to keep the entire Element visible, rather than cropping it.
style.left = (hcenter - (zoneData.width / 2)) + "px";
} else {
style.display = "none";
}
}
function getIntersectionHorizontalCenter(bounds1, bounds2) {
var west1 = bounds1.getWest(),
west2 = bounds2.getWest(),
westIn = west1 < west2 ? west2 : west1,
east1 = bounds1.getEast(),
east2 = bounds2.getEast(),
eastIn = east1 < east2 ? east1 : east2;
return (westIn + eastIn) / 2;
}
function setMapContainerWidth() {
mapContainerWidth = map.getSize().x;
}
答案 1 :(得分:2)
通常会使用L.Control创建自定义控件,然后可以将其添加到控件层。如果这样做,传单将在调整地图大小时进行定位。看看L.Control的参考文献:http://leafletjs.com/reference.html#control
在引用中有一个自定义控件的示例:http://leafletjs.com/reference.html#icontrol如果您想查看更多示例,可以查看其中一个自定义控件插件,看看它们是如何实现的.Control:{{ 3}}(在控制和互动下)
L.Control的唯一缺点是您无法垂直或水平居中定位控件。您只能使用topleft,topright,bottomleft&amp; bottomright。