我正在将 Google Maps 合并到我的 MVC 4 应用程序中。做起来相当简单。但是,我有一个关于动态添加多个标记的最佳方法的问题。我的用户将通过调用控制器上的操作方法来搜索待售商品列表,并且我希望能够向他们展示商品以及每个商品在地图上的位置。我不确定如何或最好的方式将标记动态添加到地图中,这是客户端中的所有 JavaScript。本质上,我希望能够将所有标记信息从 MVC 服务器代码发送到客户端,但不确定是否可以或应该这样做。
4 回答
在我现在正在做的项目中,我们是这样处理的:
让主 ViewModel 被调用FooViewModel
。
视图模型:
public class FooViewModel
{
// Your search results:
public IEnumerable<FooWithLocationViewModel> Foos { get; set; }
// Properties for your search filter:
public decimal? MaxPrice { get; set; }
public CityEnum? City { get; set; }
...
}
public class FooWithLocationViewModel
{
public string Name { get; set; }
public decimal Price { get; set; }
...
public double Latidude { get; set; }
public double Longitude { get; set; }
...
}
在视图中,有一个<div>
for each FooWithLocationViewModel
。我们将使用data-*
HTML5 中有效的属性:
看法:
@model FooViewModel
...
@foreach(FooWithLocationViewModel foo in Model.Foos)
{
<div class="foo" data-latitude="@(foo.Latitude)"
data-longitude="@(foo.Longitude)">
<span>@foo.Name</span>
<span>@foo.Price</span>
...
</div>
}
<div id="map-canvas"></div>
现在,是 JavaScript 的时候了,我假设您正在使用 JQuery:
初始化地图,添加标记并将它们存储在markers
数组中:
function initialize() {
var foos = $(".foo");
var markers = new Array();
var mapOptions = {
...
}};
var mapCanvas = document.getElementById('map-canvas');
if (mapCanvas != null) {
map = new google.maps.Map(mapCanvas, mapOptions);
$.each(foos, function (key, value) {
markers[key] = new google.maps.Marker({
map: map,
draggable: false,
animation: google.maps.Animation.DROP,
position: new google.maps.LatLng(
Number($(value).attr("data-latitude")),
Number($(value).attr("data-longitude")
));
});
google.maps.event.addListener(markers[key], 'click', function () {
// If you need this...
});
});
}
}
这种方法的好处是,一切都在初始化你的谷歌地图的函数中完成。因此,您的脚本不必嵌入到您的视图中。我们正在使用 HTML5 友好的方法。这很简单。
使用 Web API 并异步处理它。将 JSON 对象传递回客户端,解析您的信息,删除旧标记并添加新标记。
在您发表评论后进行编辑:
如果您发布了一些您尝试过但无法开始工作的内容,那么我们可以帮助您解决您遇到的问题。如果您刚刚开始:
http://www.asp.net/web-api - 关于使用 Web API 的精彩教程 http://angularjs.org/ - 查看 Angular 的 GET 请求 ( http://docs.angularjs.org/api/ ng .$http) 并将结果绑定到 UI
以下是我对这个问题的看法。
最近,我做了一个项目,它是一个单页、AJAX 驱动的 Web 应用程序(我知道您不是在寻找基于 AJAX 的解决方案,而是留在我身边)。
我在该应用程序中集成了谷歌地图,用于显示不同实体的位置。
当用户搜索某些内容时,我没有在浏览器中进行地理编码(有时非常慢),而是将请求发送到服务器。在服务器上,传入的文本是地理编码的(使用 Google API),结果缓存在本地数据库中供以后使用。如果再次出现相同的请求,我会从数据库中获取地理坐标并将其发送回客户端。
返回类型非常简单。IE
public class Marker
{
public double Lat{set;get;}
public double Lon{set;get;}
public string Title{set;get;}
}
在客户端,我会简单地遍历列表并在地图上绘制标记(绘制标记比请求地理编码更快)。
现在,同样可以在回发中完成。您所要做的就是在您的初始化函数调用中
var markers = @Html.Action("GetMarkers")
这将使用您可以迭代的所有标记列表填充 var 标记。
记住,返回类型GetMarkers
是
public JsonResult GetMarkers()
{
...
// returns List<Markers>
}
想为这个要求提出一种方法:
在搜索按钮上单击 - 无论是(POST 请求还是 AJAX POST),将请求发送到服务器。
在服务器“search()”操作上执行搜索。
search() 动作有两个职责 - 1. 显示搜索结果。2.在地图上显示相应的标记
搜索结果将是数据和表示形式,无论是“div”/“table/tr/td”。这种表示是在服务器上生成的,不使用任何客户端资源和客户端处理时间。所以“SearchView”可以返回数据和表示。
另一个职责是显示与每个搜索结果对应的标记。这完全是客户的责任。因此,让我们将其与第一个责任分开。使用 JSON 序列化库在 'SearchView' 中注入序列化的 'markers' json 数组,而不是将其与搜索结果混合。唯一可能希望标记详细信息与每个搜索结果紧密绑定的情况是,当您希望在单击单个搜索结果时突出显示标记。用例最初可以显示所有搜索结果并显示所有标记。然后,当用户单击/悬停在单个搜索结果上时(考虑到这不是针对移动设备的,因为悬停不能在那里工作),您可以重新定位标记或将标签或更多信息添加到选定的搜索结果。
此外,您可能希望将脚本放在单独的文件中,以避免在每个搜索操作中加载它。在 SearchView 中,您只需调用“InitializeMap()”JS 函数,将 JSON 序列化标记和初始地图位置传递给它。
使用 JSON 将是更好的方法,它提供了未来将应用程序轻松转换为 AJAX 的灵活性。此外,它比使用 Jquery 解析 HTML 来获取标记详细信息要快。
function InitializeMap(initialMapPosition,markers){ var latlng = new google.maps.LatLng(initialMapPosition.latitude,initialMapPosition.longitude); var options = { zoom: 15, center: latlng, mapTypeId: google.maps.MapTypeId.ROADMAP // this could be as per your requirement. }; var map = new google.maps.Map($('#map-canvas')[0], options); // Place markers on map for( i = 0; i < markers.length; i++) { var latLng = new google.maps.LatLng(markers[i].lat, markers[i].lng); var marker = new google.maps.Marker({ position: latLng, map: map }); }
}