我正在使用Web应用程序,并且使用Ruby on Rails。我们的索引由地图和搜索字段组成。您可以搜索位置,地图会更新其标记。
我想使用Ajax来避免刷新页面。因此,我在控制器中添加remote: true了一个respond_to,新的search.js.erb.My search.js.erb渲染了一个部分_googlemap.erb,其中包含用于初始化地图的脚本。
remote: true
respond_to
search.js.erb.
search.js.erb
_googlemap.erb
这是我的问题。既然地图已经存在,就好像我想两次创建相同的对象一样,这当然不起作用,而且效果很糟。我只想用新标记更新地图中的标记。但是我找不到办法。
我看到旧版的Gmaps4rails集成了一种实现方法(Gmaps.map.replaceMarkers(your_markers_json_array);),但现在似乎不起作用。使用它时,出现以下错误:“ TypeError: Gmaps.map is undefined”。我尝试使用“ handler.replaceMarkers();”,但是这次我使用了“ TypeError: handler.replaceMarkers is not a function”。
Gmaps.map.replaceMarkers(your_markers_json_array);
TypeError: Gmaps.map is undefined
handler.replaceMarkers();
TypeError: handler.replaceMarkers is not a function
我是Java和Rails的新手,但是我想提高自己的知识,并且确实需要继续进行本Web应用程序的其余部分。我一直在互联网上到处寻找解决方案,但徒劳。
拜托,有人可以告诉我我该怎么做以及我做错了什么吗?
提前谢谢了,
席琳
zone_controller.rb
def search respond_to do |format| format.html.none do search_params = params[:zone][:search] coordinates = Geocoder.coordinates(search_params).join(",") @zones = Zone.search( "", { "aroundLatLng" => coordinates, "aroundRadius" => 500000 #Searches around 500 km }) if coordinates.nil? @zones = Zone.search(params[:search]) elsif @zones.empty? @zones = Zone.all flash[:error] = "No zone could be found. Please try again." end build_map(@zones) end format.js end end def build_map(array) @hash = Gmaps4rails.build_markers(array) do |zone, marker| marker.lat zone.latitude marker.lng zone.longitude marker.json({ title: zone.description, id: zone.id }) marker.infowindow render_to_string(:partial => "/zones/map_box", locals: { zone: zone }) end end
search.html.erb
<div id="map" style='width: 100%; height: 700px;'> </div> <!-- Beginning Google maps --> <script type="text/javascript" id="map_script"> $(document).ready(function() { <%= render 'googlemap', hash: @hash %> }); // Document ready </script>
handler = Gmaps.build('Google'); handler.buildMap({ provider: { disableDefaultUI: true, mapTypeId: google.maps.MapTypeId.TERRAIN }, internal: {id: 'map'} }, function(){ markers_json = <%= raw hash.to_json %>; markers = _.map(markers_json, function(marker_json){ marker = handler.addMarker(marker_json); handler.getMap().setZoom(4); _.extend(marker, marker_json); marker.infowindow = new google.maps.InfoWindow({ content: marker.infowindow }); return marker; }); handler.bounds.extendWith(markers); handler.fitMapToBounds(); });
$('#map_script').replaceWith("<%= render 'googlemap', hash: @hash %>");
您为什么不只使用新标记更新地图?意思是,无需在每次搜索后重新渲染整个地图,只需通过删除所有标记并添加新标记来更新现有地图上的标记。
我尚未验证该方法,但我想它应该可以工作并且效率更高:
创建一个app/assets/javascript/map.js文件。您可以在此处存储与地图相关的功能。创建一个函数来更新此文件中的地图标记:
app/assets/javascript/map.js
map.js
(function() { /* __markers will hold a reference to all markers currently shown on the map, as GMaps4Rails won't do it for you. This won't pollute the global window object because we're nested in a "self-executed" anonymous function */ var __markers; function updateMarkers(map, markersData) { // Remove current markers map.removeMarkers(__markers); // Add each marker to the map according to received data __markers = _.map(markersData, function(markerJSON) { marker = map.addMarker(markerJSON); map.getMap().setZoom(4); // Not sure this should be in this iterator! _.extend(marker, markerJSON); marker.infowindow = new google.maps.InfoWindow({ content: marker.infowindow }); return marker; }); map.bounds.extendWith(__markers); map.fitMapToBounds(); }; // "Publish" our method on window. You should probably have your own namespace window.updateMarkers = updateMarkers; })();
此功能可用于初始化地图并进行更新。由于您不会(如果我的回答令人满意)两次渲染地图,因此您可以删除,_google_map.erb然后将其内容放回search.html.erb,但是使用我们刚刚创建的功能:
_google_map.erb
<div id="map" style='width: 100%; height: 700px;'> </div> <!-- Beginning Google maps --> <script type="text/javascript" id="map_script"> $(document).ready(function() { mapHandler = Gmaps.build('Google'); mapHandler.buildMap({ provider: { disableDefaultUI: true, mapTypeId: google.maps.MapTypeId.TERRAIN }, internal: {id: 'map'} }, function(){ var markersData = <%= raw @hash.to_json %>; updateMarkers(mapHandler, markersData); }); }); // Document ready </script>
声明变量时,请 不要忘记var关键字 ,否则它们最终将成为全局变量,这很糟糕^^ 请注意,我故意将其保留mapHandler为全局变量:稍后当有人使用时,您将需要访问处理程序以更新标记搜索。这可能不是理想的事情,但是这个问题不是关于重构代码的,所以让我们保持这种方式。
mapHandler
因此,现在我的解决方案为您带来了一张地图,该地图在页面加载时使用给定的标记进行了初始化。换句话说,什么都没有改变!
但是,现在允许您重复使用此updateMarkers功能来更改地图上显示的标记。那就是您的search.js.erb脚本应该执行的操作:
updateMarkers
(function() { var markersData = <%= raw @hash.to_json %>; updateMarkers(mapHandler, markersData); })();
而已!希望它将带您进入项目的下一步:)