将 Google 地图标记绑定到非地图侧边栏条目
Posted
技术标签:
【中文标题】将 Google 地图标记绑定到非地图侧边栏条目【英文标题】:Binding Google Map Markers to non-map Sidebar Entries 【发布时间】:2012-05-22 10:31:09 【问题描述】:我正在尝试在 Google Map V3 标记上的事件侦听器和地图外边栏条目之间添加 2 路绑定。我寻求实现这一目标的示例,但无法找到最佳实践。在 Google Maps API V3 发布后,ESA 2009 能够在侧边栏条目和标记之间建立这种类型的关联。是否有一种现代方法可以实现这一点,可能使用 jQuery.Callbacks()?这个ESA 2009 Example 已经存在 3 年了,但是很少有(如果有的话)成功的模拟实现能够在标记和相应的非地图侧边栏条目之间干净地复制 ESA 2009 优雅的双向绑定功能。 This PlugIn 是一个很好的开始,但是当直接单击标记时,JQuery 缺乏突出或识别所选侧边栏项目的能力。
ESA 2009 方法在 SidebarItem() 和 makeMarker() JS 函数中使用内部函数、闭包和原型来建立侧边栏条目和标记之间的双向绑定。单击标记时,侧边栏条目会突出显示(反之亦然),而不会出现明显的内存泄漏或过度递归。 ESA 2009 技术在概念上对我来说很难掌握或扩展。这种行为很有用,但没有被广泛采用。当用户单击侧边栏项目时,会出现典型的 Google 地图行为:地图平移和信息窗口打开。这是标准的,但在 ESA 2009 版本中还有一个额外的部分,即非地图侧边栏项目监听和响应(通过带有焦点的 CSS)到相应的标记点击。这种 2-way listener 效果很难通过 JQuery 移植,或者很难在任何最近的商店定位器解决方案中本地合并。所需的功能是:
当用户点击一个标记或它的侧边栏条目时,现有的高亮将被清除并打开选定的信息窗口和相应的侧边栏 项目被并行识别...反之亦然。
实现这种有用效果的最佳做法是什么?有谁知道集成双向触发器的当前示例?如何在从 Google 服务器呈现的特定标记与同一页面上但在地图之外的相应事件侦听器(例如,侧边栏项目)之间最好地实现链接。我们是否应该使用任何 JQuery 最新的(1.7)回调处理功能?有更好的非 JQuery 技术吗?
下面是熟悉的“最先进”的 sn-p 在名为“map”的 Map() 上创建 Marker 和 InfoWindow,并在名为“sidebar”的 DIV 中创建边栏行,其中包含 markerArray 和 markerBounds标记。 SidebarItem() 构造函数由 ESA 2009 的优秀示例中的 makeMarker() 函数调用:
var infoWindow = new google.maps.InfoWindow();
var markerBounds = new google.maps.LatLngBounds();
var markerArray = [];
function makeMarker(options)
var pushPin = new google.maps.Marker(map:map);
pushPin.setOptions(options);
google.maps.event.addListener(pushPin, "click", function()
infoWindow.setOptions(options);
infoWindow.open(map, pushPin);
if(this.sidebarButton)this.sidebarButton.button.focus();
);
var idleIcon = pushPin.getIcon();
if(options.sidebarItem)
pushPin.sidebarButton = new SidebarItem(pushPin, options);
pushPin.sidebarButton.addIn("sidebar");
markerBounds.extend(options.position);
markerArray.push(pushPin);
return pushPin;
google.maps.event.addListener(map, "click", function()
infoWindow.close();
);
function SidebarItem(marker, opts)
var tag = opts.sidebarItemType || "button";
var row = document.createElement(tag);
row.innerhtml = opts.sidebarItem;
row.className = opts.sidebarItemClassName || "sidebar_item";
row.style.display = "block";
row.style.width = opts.sidebarItemWidth || "120px";
row.onclick = function()
google.maps.event.trigger(marker, 'click');
row.onmouseover = function()
google.maps.event.trigger(marker, 'mouseover');
row.onmouseout = function()
google.maps.event.trigger(marker, 'mouseout');
this.button = row;
// adds a sidebar item to a
SidebarItem.prototype.addIn = function(block)
if(block && block.nodeType == 1)this.div = block;
else
this.div = document.getElementById(block)
|| document.getElementById("sidebar")
|| document.getElementsByTagName("body")[0];
this.div.appendChild(this.button);
// deletes a sidebar item
SidebarItem.prototype.remove = function()
if(!this.div) return false;
this.div.removeChild(this.button);
return true;
SidebarItem() 和 makeMarker() 是公共领域的函数,但对于像我这样的新手来说,它们很难理解、采用和集成。任何建议或当前示例将不胜感激。具体来说,ESA 2009 方法是否已经过时?我没有发现这种策略的最新用法。将非地图 DOM 元素与特定 Google 地图标记相关联的最佳现代方法是什么?
提前谢谢...
【问题讨论】:
【参考方案1】:我认为您要实现的目标没有什么神奇之处,但您确实需要了解变量范围。最简单的方法是声明地图标记和侧边栏条目,并在同一范围内(例如在 onload 处理程序中)定义它们的事件处理程序,以便它们可以相互寻址。我没有详细浏览过你的代码,所以你在这方面可能已经没问题了。
您可能还想尝试使用.triggerHandler()
而不是.trigger()
否则A 将触发B 并且B 将立即触发A 等等。如果是这样,那么调用堆栈可能会填满或浏览器可能会抓住。
编辑:
这里有类似的东西,取自一个应用程序,其中谷歌地图标记和相应的外部链接都被赋予了 mouseover 和 mouseout 处理程序以相互突出显示。整个应用程序有数千行长,并组织成命名空间,每个命名空间都有一个大写的名称(例如GOOGLEMAP
、DATA
)。
您将看到数据结构DATA.locationData
是标记和外部链接之间交互的关键。它允许处理程序在不同的命名空间(即不同的范围)中附加到链接和标记。
命名空间“GOOGLEMAP”(简体):
var GOOGLEMAP = (function()//NAMESPACE pattern
//...
var mouseoverLocMarker_closure = function(loc)
return function()
$(loc.link).addClass('hilight');
;
;
var mouseoutLocMarker_closure = function(loc)
return function()
$(loc.link).removeClass('hilight');
;
;
//...
var init = function(...)
//...
for(var name in DATA.locationData)
//...
var loc = DATA.locationData[name];//lookup in a large hardcoded data structure in the DATA namespace
loc.marker = new google.maps.Marker( map:map, icon:'images/symbols/green.gif', zIndex:0 );//makes the marker available in other scopes
//Here we attach functions returned by "_closure" functions, in order to correctly remember loc.
google.maps.event.addListener( loc.marker, 'mouseover', mouseoverLocMarker_closure(loc) );
google.maps.event.addListener( loc.marker, 'mouseout', mouseoutLocMarker_closure(loc) );
//...
;
//...
)();
一个 jQuery“文档就绪”闭包(简化):
$(function()
$('#towns a.location').each(function()
//...
var loc = DATA.locationData[name];//lookup in a large hardcoded data structure in the DATA namespace
if(loc)
//...
$this.mouseover(function()
if(loc.marker)
loc.icon = loc.marker.getIcon();
loc.marker.setIcon('images/symbols/red.gif');
);
$this.mouseout(function()
if(loc.marker)
loc.marker.setIcon(loc.icon);
);
loc.link = this;//makes the link available to other scopes
else
//...
);
//...
);
老实说,我不能说这段代码是典型的——它可能更有效地使用内存——但它组织得很好并且非常可靠。
【讨论】:
谢谢。欣赏范围提示,但不要认为这是困难所在。将检查 .triggerHandler 方法。您是否知道任何主要商店定位器上的双触发示例性实施? @BogieCoder,查看我的编辑以获取具有类似目标的代码示例。 感谢@Beetroot-Beetroot。将研究该解决方案,这是我正在寻找的策略类型。以上是关于将 Google 地图标记绑定到非地图侧边栏条目的主要内容,如果未能解决你的问题,请参考以下文章
在 jQuery Mobile 中使用 longclick/taphold 和 Google 地图?