0

我正在尝试在 Google Map V3 标记和地图外边栏条目上的事件侦听器之间添加 2 路绑定。我寻求实现这一目标的示例,但无法找到最佳实践。在 Google Maps API V3 发布后,ESA 2009 能够在侧边栏条目和标记之间建立这种类型的关联。是否有一种现代方法可以实现这一点,可能使用 jQuery.Callbacks()?这个ESA 2009 示例已经使用了 3 年,但是很少有(如果有的话)成功的模拟实现能够在标记和相应的非地图侧边栏条目之间干净地复制 ESA 2009 优雅的双向绑定功能。这个插件是一个很好的开始,但是当直接单击标记时,JQuery 缺乏突出或识别所选侧边栏项目的能力。

ESA 2009 方法在 SidebarItem() 和 makeMarker() JS 函数中使用内部函数、闭包和原型来建立侧边栏条目和标记之间的双向绑定。单击标记时,侧边栏条目会突出显示(反之亦然),而不会出现明显的内存泄漏或过度递归。ESA 2009 技术在概念上对我来说很难掌握或扩展。这种行为很有用,但没有被广泛采用。当用户单击侧边栏项目时,会出现典型的 Google 地图行为:地图平移和信息窗口打开。这是标准的,但在 ESA 2009 版本中还有一个额外的部分,即非地图侧边栏项目监听和响应(通过带有焦点的 CSS)到相应的标记点击。这种 2-way listener 效果很难通过 JQuery 移植,或者很难在任何最近的商店定位器解决方案中本地合并。所需的功能是:

当用户单击标记或其侧边栏条目时,现有突出显示将被清除并打开选定的信息窗口并并行识别相应的侧边栏项目......反之亦然。

实现这种有用效果的最佳实践是什么?有谁知道集成双向触发器的当前示例?如何在从 Google 服务器呈现的特定标记与同一页面上但在地图之外(例如,侧边栏项目)的相应事件侦听器之间实现最佳链接。我们是否应该使用任何 JQuery 最新的(1.7)回调处理功能?有更好的非 JQuery 技术吗?

下面是“最先进的”熟悉的片段,在名为“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 地图标记相关联的最佳现代方式是什么?

提前致谢...

4

1 回答 1

0

我认为您要实现的目标没有任何魔力,但您确实需要注意变量范围。最简单的方法是声明地图标记和侧边栏条目,并在同一范围内(例如在 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 {
            //...
        }
    });
    //...
});

老实说,我不能说这段代码是典型的——它可能更有效地使用内存——但它组织得很好并且非常可靠。

于 2012-05-15T01:13:42.350 回答