冷聚变 +谷歌地图 API v3 ߞ信息窗口和设置边界

发布于 2024-09-26 13:09:09 字数 3961 浏览 0 评论 0原文

简而言之,我似乎能够编写代码,为弹出信息窗口创建可点击标记,或者获取返回标记的边界并重置地图范围和缩放级别。我似乎无法将两者结合起来。 我下面的示例将很好地将地图的范围设置为查询的结果。但考虑到我的循环结构,我不太知道如何将 addListener 事件包含到标记中,并且在 var mapOptions 中,我设置了 center:gbounds.getCenter()。这两个问题似乎使我向地图或标记添加事件的能力变得复杂。

    <cfquery name="myquery" datasource="xxxx">
       SELECT name, lat, long
       FROM tblMain
    </cfquery>

    <cfset bridgeCoord=arrayNew(1)>

    <cfloop query="myquery">
   <cfset bridge[CurrentRow] = structNew()>
   <cfset bridge[CurrentRow].lat=lat>
       <cfset bridge[CurrentRow].long=longX>
          <cfset bridge[CurrentRow].name=name>
     </cfloop>



     <script>
       $(document).ready(function() {
       var gbounds = new google.maps.LatLngBounds();
        var markers = [];


       <cfloop index="mi" array="#bridge#">
           <cfoutput> 
               //make the point
               var point = new google.maps.LatLng(#mi.lat#,#mi.long#);
               gbounds.extend(point);
               //make the marker
               var marker = new google.maps.Marker({position: point, title:"#mi.name#"});
               markers[markers.length] = marker; 
            </cfoutput>
       </cfloop>

              var mapOptions = {
                    zoom:3,
                    mapTypeControl: true,
                    mapTypeControlOptions: {
                    style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
                       },
                     mapTypeId:google.maps.MapTypeId.ROADMAP,
                     center:gbounds.getCenter()
                        };



        var map = new google.maps.Map(document.getElementById('myMap'), mapOptions);

           map.fitBounds(gbounds);

           for(var i=0; i<markers.length; i++) markers[i].setMap(map);

      });

仅供参考,我还尝试组织部分代码,如下所示。 这非常适合将点击事件添加到标记,但我似乎无法使用我的 center:gbounds.getCenter() 或 map.fitBounds() 元素 b/c 首先设置 mapOptions并传递给新的地图变量,并且此时尚未定义 gbounds。将纬度/经度硬编码到中心:似乎只是将其保留在那里。

       function initialize() {

    var gbounds = new google.maps.LatLngBounds();    


  var myOptions = {
    zoom: 4,
    center: new google.maps.LatLng(39.0,-94.1),
    mapTypeControl: true,
    mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
    navigationControl: true,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  }
  map = new google.maps.Map(document.getElementById("myMap"),
                                myOptions);

  google.maps.event.addListener(map, 'click', function() {
        infowindow.close();
        });

  // Add markers to the map
  // Set up three markers with info windows 

    <cfloop index="mi" array="#bridge#">
        <cfoutput>

             //make the point
               var point = new google.maps.LatLng(#mi.lat#,#mi.long#);
            gbounds.extend(point);
            //make the marker
               var marker = createMarker(point, "#mi.name#", "#mi.name#")

        </cfoutput>
    </cfloop>


}
 map.fitBounds(gbounds);;

function createMarker(latlng, tip, html) {
    var contentString = html;
    var marker = new google.maps.Marker({
        position: latlng,
        title: tip,
        map: map,
        });

    google.maps.event.addListener(marker, 'click', function() {
        infowindow.setContent(contentString); 
        infowindow.open(map,marker);
        });
}


var infowindow = new google.maps.InfoWindow(
  { 
    size: new google.maps.Size(150,50)
  });

10/12 更新: 让它工作了。泰勒的代码中确实有一个拼写错误,但很小。我不确定我能如何很好地使用这段代码并对其进行扩展,因为我不太熟悉 jQuery,但这只是一个开始。我正在努力解决的一件事是,当返回零标记时如何处理地图。我的查询中可能没有返回任何记录。所发生的情况是,地图已绘制,但它以海洋中央为中心并缩放。我认为它应该默认为我设置的中心(center: new google.maps.LatLng(39, -94.1),但事实并非如此。

Replace: 

var $markers = $container.find(".map-marker");

with

var $markers = $container.find(".mapMarker");

Simply, I seem to be able to write code that either creates a clickable marker for a pop-up infoWindow OR gets the bounds of the returned markers and resets the map extent and zoom levels. I can't seem to combine the two. My example below will nicely set the extent of the map to the results of the query. But I don't quite know how to include the addListener event to the marker given how my loop is structured, and that in the var mapOptions, I set center: gbounds.getCenter(). These two issues seem to complicate my ability to add events to the map or marker.

    <cfquery name="myquery" datasource="xxxx">
       SELECT name, lat, long
       FROM tblMain
    </cfquery>

    <cfset bridgeCoord=arrayNew(1)>

    <cfloop query="myquery">
   <cfset bridge[CurrentRow] = structNew()>
   <cfset bridge[CurrentRow].lat=lat>
       <cfset bridge[CurrentRow].long=longX>
          <cfset bridge[CurrentRow].name=name>
     </cfloop>



     <script>
       $(document).ready(function() {
       var gbounds = new google.maps.LatLngBounds();
        var markers = [];


       <cfloop index="mi" array="#bridge#">
           <cfoutput> 
               //make the point
               var point = new google.maps.LatLng(#mi.lat#,#mi.long#);
               gbounds.extend(point);
               //make the marker
               var marker = new google.maps.Marker({position: point, title:"#mi.name#"});
               markers[markers.length] = marker; 
            </cfoutput>
       </cfloop>

              var mapOptions = {
                    zoom:3,
                    mapTypeControl: true,
                    mapTypeControlOptions: {
                    style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
                       },
                     mapTypeId:google.maps.MapTypeId.ROADMAP,
                     center:gbounds.getCenter()
                        };



        var map = new google.maps.Map(document.getElementById('myMap'), mapOptions);

           map.fitBounds(gbounds);

           for(var i=0; i<markers.length; i++) markers[i].setMap(map);

      });

fyi, I've also tried organizing part of the code, like below. this works great for adding the click event to the marker but then I can't seem to use my center:gbounds.getCenter() or map.fitBounds() elements b/c the mapOptions get set first and passed to the new map variable and gbounds hasn't been defined by that point. Hardcoding lat/long to center: seems to just keep it there.

       function initialize() {

    var gbounds = new google.maps.LatLngBounds();    


  var myOptions = {
    zoom: 4,
    center: new google.maps.LatLng(39.0,-94.1),
    mapTypeControl: true,
    mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
    navigationControl: true,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  }
  map = new google.maps.Map(document.getElementById("myMap"),
                                myOptions);

  google.maps.event.addListener(map, 'click', function() {
        infowindow.close();
        });

  // Add markers to the map
  // Set up three markers with info windows 

    <cfloop index="mi" array="#bridge#">
        <cfoutput>

             //make the point
               var point = new google.maps.LatLng(#mi.lat#,#mi.long#);
            gbounds.extend(point);
            //make the marker
               var marker = createMarker(point, "#mi.name#", "#mi.name#")

        </cfoutput>
    </cfloop>


}
 map.fitBounds(gbounds);;

function createMarker(latlng, tip, html) {
    var contentString = html;
    var marker = new google.maps.Marker({
        position: latlng,
        title: tip,
        map: map,
        });

    google.maps.event.addListener(marker, 'click', function() {
        infowindow.setContent(contentString); 
        infowindow.open(map,marker);
        });
}


var infowindow = new google.maps.InfoWindow(
  { 
    size: new google.maps.Size(150,50)
  });

UPDATE 10/12:
Got it to work. There is indeed a typo in Tyler's code but it's minor. I'm not sure how well I can take this code and expand on it since I'm not very versed in jQuery but this is a start. One thing it doesn't do that I'm struggling with is how to deal w/the map when zero markers are returned. It is possible in my query that no records can be returned. What happens is that the map draws but it is centered and zoomed in the middle of the ocean. I figured it should default to the center I set up (center: new google.maps.LatLng(39, -94.1) but it doesn't.

Replace: 

var $markers = $container.find(".map-marker");

with

var $markers = $container.find(".mapMarker");

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

兰花执着 2024-10-03 13:09:09

编辑

实际上我大约一个月前才处理过这个问题,这里有一些对我有用的修改代码,使其更像你的。

Google Maps API v3 和 jQuery 1.4.2(尽管这应该适用于任何版本的 jQuery,并将其移植到 strait javascript 或其他库应该很简单)

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script src="http://maps.google.com/maps/api/js?sensor=false" type="text/javascript"></script>

<cfquery name="mi" datasource="xxxx">
SELECT name, lat, long, content
FROM tblName
</cfquery>

<ul id="mapMarkers">
<cfoutput query="mi">
    <li class="mapMarker" data-latitude="#mi.lat#" data-longitude="#mi.long#">
        <div class="info-window">
        <h1 class="name">#mi.name#</a></h1>
        <div class="content">#mi.content#</div>
        </div>
    </li>
</cfoutput>
</ul>
<div id="map"></div>

<script type="text/javascript">
$(function() {
    var $container = $("#mapMarkers");

    var $map = $("#map");
    var $markers = $container.find(".map-marker");

    var bounds = new google.maps.LatLngBounds();
    var infowindow = new google.maps.InfoWindow({
        maxWidth: 300
    });

    var gmap = new google.maps.Map($map[0], {
        zoom: 8
        , mapTypeId: google.maps.MapTypeId.ROADMAP
    });

    $markers.each(function(){
        $this = $(this);
        var latitude = $this.attr("data-latitude");
        var longitude = $this.attr("data-longitude");
        var content = $this.find(".info-window").remove().html();
        var latlng = new google.maps.LatLng(latitude, longitude);

        bounds.extend(latlng);

        var marker = new google.maps.Marker({
            position: latlng
            , map: gmap
        });

        google.maps.event.addListener(marker, 'click', function() {
            infowindow.setContent(content);
            infowindow.open(this.map, this);
        });

        google.maps.event.addListener(gmap, 'click', function() {
            infowindow.close();
        });

        $this.click(function(e, el) {
            e.preventDefault();

            infowindow.setContent(content);
            infowindow.open(gmap, marker);
        })
    });

    if($markers.length > 1)
        gmap.fitBounds(bounds);
    else
        gmap.setCenter(bounds.getCenter());

    $container.hide();
});
</script>

END EDIT

首先,您必须移动地图和mapOptions到顶部。然后在循环内只需将 addListener 添加到标记的地图中:

<cfloop index="mi" array="#bridge#">
   <cfoutput> 
       //make the point
       var point = new google.maps.LatLng(#mi.lat#,#mi.long#);
       gbounds.extend(point);
       //make the marker
       var marker = new google.maps.Marker({position: point, title:"#JSStringFormat(mi.name)#", map:map});
       google.maps.event.addListener(marker, 'click', function() {
           infowindow.setContent("#JSStringFormat(mi.content)#");
           infowindow.open(this.map, this);
       });
       markers[markers.length] = marker; 
    </cfoutput>
</cfloop>

需要注意的事项:

我将 JSStringFormat 添加到了 name 和 content 变量中。

标记创建中有一个地图选项,您只需添加“map:map”即可,这样您就不必在底部运行 for 循环。

此外,由于您现在是在标记之前创建地图,因此您会将缩放和中心选项移至底部。

if(markers.length > 1)  
    map.fitBounds(gbounds);  
else  
    map.setCenter(gbounds.getCenter());  

最后一件事:

代替

markers[markers.length] = marker;

你可以使用这个

markers.push(marker); 

EDIT

I actually just dealt with this a month or so ago, here is some modified code from what worked for me to make it more like yours.

Google Maps API v3 and jQuery 1.4.2 (though this should prolly work with any version of jQuery, and porting it to strait javascript or another library should be cake)

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script src="http://maps.google.com/maps/api/js?sensor=false" type="text/javascript"></script>

<cfquery name="mi" datasource="xxxx">
SELECT name, lat, long, content
FROM tblName
</cfquery>

<ul id="mapMarkers">
<cfoutput query="mi">
    <li class="mapMarker" data-latitude="#mi.lat#" data-longitude="#mi.long#">
        <div class="info-window">
        <h1 class="name">#mi.name#</a></h1>
        <div class="content">#mi.content#</div>
        </div>
    </li>
</cfoutput>
</ul>
<div id="map"></div>

<script type="text/javascript">
$(function() {
    var $container = $("#mapMarkers");

    var $map = $("#map");
    var $markers = $container.find(".map-marker");

    var bounds = new google.maps.LatLngBounds();
    var infowindow = new google.maps.InfoWindow({
        maxWidth: 300
    });

    var gmap = new google.maps.Map($map[0], {
        zoom: 8
        , mapTypeId: google.maps.MapTypeId.ROADMAP
    });

    $markers.each(function(){
        $this = $(this);
        var latitude = $this.attr("data-latitude");
        var longitude = $this.attr("data-longitude");
        var content = $this.find(".info-window").remove().html();
        var latlng = new google.maps.LatLng(latitude, longitude);

        bounds.extend(latlng);

        var marker = new google.maps.Marker({
            position: latlng
            , map: gmap
        });

        google.maps.event.addListener(marker, 'click', function() {
            infowindow.setContent(content);
            infowindow.open(this.map, this);
        });

        google.maps.event.addListener(gmap, 'click', function() {
            infowindow.close();
        });

        $this.click(function(e, el) {
            e.preventDefault();

            infowindow.setContent(content);
            infowindow.open(gmap, marker);
        })
    });

    if($markers.length > 1)
        gmap.fitBounds(bounds);
    else
        gmap.setCenter(bounds.getCenter());

    $container.hide();
});
</script>

END EDIT

First you have to move the map and mapOptions to the top. Then inside your loop just add the addListener to the map for the marker:

<cfloop index="mi" array="#bridge#">
   <cfoutput> 
       //make the point
       var point = new google.maps.LatLng(#mi.lat#,#mi.long#);
       gbounds.extend(point);
       //make the marker
       var marker = new google.maps.Marker({position: point, title:"#JSStringFormat(mi.name)#", map:map});
       google.maps.event.addListener(marker, 'click', function() {
           infowindow.setContent("#JSStringFormat(mi.content)#");
           infowindow.open(this.map, this);
       });
       markers[markers.length] = marker; 
    </cfoutput>
</cfloop>

Things to note:

I added JSStringFormat to the name and content variables.

There is a map option in the marker creation that you can just add "map:map" to it so you don't have to run the for loop at the bottom.

Also, since you are now creating the map ahead of the markers you will move the zoom and center options to the bottom.

if(markers.length > 1)  
    map.fitBounds(gbounds);  
else  
    map.setCenter(gbounds.getCenter());  

Also once last thing:

Instead of

markers[markers.length] = marker;

You can use this

markers.push(marker); 
二货你真萌 2024-10-03 13:09:09

我不确定问题是什么,但如果您解开 JavaScript 和 ColdFusion 代码,您可能会发现更容易调试(和扩展)。您可以在 JS 中编写所有地图逻辑,然后使用 CF 创建 JS 将处理的数据(lat/lng/title 数组)。

<script>
// Data For Map Logic
var points = [];
<cfloop query="...">
  <cfoutput>
    points.push({lat: #db_lat#, lng: #db_lng#, etc...});
  </cfoutput>
</cfloop>

// Logic for setting map extent and creating pop-ups
for (var i = 0; i < points.length; i++) {
  // do your magic
}
</script>

使用这种方法,您可以通过对点数组进行硬编码来在测试期间完全消除 CF 和数据库。

I'm not sure what the problem is but you may find it easier to debug (and extend) if you untangle your JavaScript and ColdFusion code. You could write all the map logic in JS and then use CF to create the data (array of lat/lng/title) that the JS will process.

<script>
// Data For Map Logic
var points = [];
<cfloop query="...">
  <cfoutput>
    points.push({lat: #db_lat#, lng: #db_lng#, etc...});
  </cfoutput>
</cfloop>

// Logic for setting map extent and creating pop-ups
for (var i = 0; i < points.length; i++) {
  // do your magic
}
</script>

Using this approach you could completely eliminate CF and the database during testing by hard-coding the points array.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文