我正在编写一个MVC项目,其中包括在Google地图中添加点的可能性。到目前为止,我可以通过硬编码纬度和经度值为db添加点,但我想让用户选择地图上的位置并从Razor视图将它们发送回控制器。我已经编写了部分视图,我可以使用地图和硬编码位置打开模态弹出窗口。我想要做的是:1。让用户在文本框中插入一个地址2.打开模态弹出窗口,让地图以地址附近的标记为中心3.保存视图的两个字段中的位置,以便将它们发送回控制器。
我一直在使用Google Developers提供的代码:https://developers.google.com/maps/documentation/javascript/examples/place-details,并且已经得到以下代码:
所有代码都在Razor视图中:
<form>
<fieldset>
<legend>Ubicazione: </legend>
<div class="form-group">
@Html.LabelFor(model => model.Indirizzo, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
<button type="button" class="btn btn-default" style="float:left"
data-toggle="modal" data-target="#findInModal" data-backdrop="static"
data-keyboard="true" data-address='pippo'>
Trova posizione
</button>
@Html.EditorFor(model => model.Indirizzo, new { htmlAttributes = new { @class = "form-control" }, @id="addr" })
@Html.ValidationMessageFor(model => model.Indirizzo, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Latitudine, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@*@Html.EditorFor(model => model.Latitudine, new { htmlAttributes = new { @class = "form-control" } })*@
@Html.DisplayFor(model => model.Latitudine, new { htmlAttributes = new { @class = "form-control" } })
@Html.HiddenFor(model => model.Latitudine)
@Html.ValidationMessageFor(model => model.Latitudine, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Longitudine, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@*@Html.EditorFor(model => model.Longitudine, new { htmlAttributes = new { @class = "form-control" } })*@
@Html.DisplayFor(model => model.Longitudine, new { htmlAttributes = new { @class = "form-control" } })
@Html.HiddenFor(model => model.Longitudine)
@Html.ValidationMessageFor(model => model.Longitudine, "", new { @class = "text-danger" })
</div>
</div>
</fieldset>
</form>
我希望data-address ='pippo'的值是“@ Html.EditorFor(model => model.Indirizzo ...”中的地址)。
以下是模式弹出窗口内容,用于打开地图并将其置于硬编码位置:
<!-- Find Location In Modal -->
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="modal fade" id="findInModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" style="height: 0px;"></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Chiudi">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div id="gMap" style="height:400px;width:100%;"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=APIKEY&language=it®ion=IT&libraries=places&callback=gMap" async defer></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script>
let myCenter;
let mapProp;
let map;
let service;
function gMap() {
myCenter = new google.maps.LatLng(41.893140, 12.483330);
mapProp = { center: myCenter, zoom: 15, scrollwheel: true, draggable: true, mapTypeId: google.maps.MapTypeId.HYBRID };
map = new google.maps.Map(document.getElementById("gMap"), mapProp);
let request = {
query: 'Musei Capitolini',
fields: ['name', 'geometry'],
};
service = new google.maps.places.PlacesService(map);
service.findPlaceFromQuery(request, function (results, status) {
if (status === google.maps.places.PlacesServiceStatus.OK) {
for (let i = 0; i < results.length; i++) {
createMarker(results[i]);
}
map.setCenter(results[0].geometry.location);
}
});
}
function createMarker(place) {
let marker = new google.maps.Marker({
map: map,
position: place.geometry.location,
icon: "/Content/icons/01.png"
});
google.maps.event.addListener(marker, 'click', function () {
infowindow.setContent(place.name + place.geometry.location);
infowindow.open(map, this);
});
}
</script>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Chiudi</button>
<button type="button" class="btn btn-primary">Salva</button>
</div>
</div>
</div>
</div>
}
这是打开弹出窗口的脚本:
<script>
$('#findInModal').on('show.bs.modal', function (event) {
let button = $(event.relatedTarget) // Button that triggered the modal
let AddressToFind = button.data('address') // Extract info from data-* attributes
// If necessary, you could initiate an AJAX request here (and then do the updating in a callback).
// Update the modal's content. We'll use jQuery here, but you could use a data binding library or other methods instead.
let modal = $(this)
modal.find('.modal-title').text('Find near: ' + AddressToFind)
})
</script>
目前我还没有实现如何将place.geometry.location值返回到父视图,但是他们假设更新了model => model.Latitudine和model => model.Longitudine值将返回给控制器更新数据库。
提前感谢您的帮助。
没有开发人员的帮助,但深入了解Google Developers文档并在JSFiddle上测试它,我终于推出了以下解决方案:
@model GoogleMapTest.Models.MapPoint
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<fieldset>
<legend>MapPoint</legend>
<div class="form-group">
<div class="editor-label">
@Html.LabelFor(model => model.Address)
</div>
<div class="editor-field">
@Html.DisplayFor(model => model.Address)
@Html.HiddenFor(model => model.Address, new { id = "Address" })
@Html.ValidationMessageFor(model => model.Address)
</div>
<button type="button" class="btn btn-default" style="float: left"
data-toggle="modal" data-target="#findInModal" data-backdrop="static"
data-keyboard="true">
Find Position
</button>
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Latitude)
</div>
<div class="editor-field">
@Html.DisplayFor(model => model.Latitude)
@Html.HiddenFor(model => model.Latitude, new { id = "Latitude" })
@Html.ValidationMessageFor(model => model.Latitude)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Longitude)
</div>
<div class="editor-field">
@Html.DisplayFor(model => model.Longitude)
@Html.HiddenFor(model => model.Longitude, new { id = "Longitude" })
@Html.ValidationMessageFor(model => model.Longitude)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
<!-- Find Location In Modal -->
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="modal fade" id="findInModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" style="height: 0px;">Set Point in Map</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<input id="pac-input" class="controls" type="text" placeholder="Find...">
<div id="gMap" style="height:400px;width:100%;"></div>
<script src="https://maps.google.com/maps/api/js?sensor=false&key=AIzaSyDMD8_QumYpomzDTcHW-myppqsyCZRsnB8"
// APIkey end with call to libraries "&libraries=places&callback=initAutocomplete"
async defer></script>
<script>
function initAutocomplete() {
var map = new google.maps.Map(document.getElementById('gMap'), {
center: { lat: 41.893321, lng: 12.482929 },
zoom: 13,
mapTypeId: 'hybrid',
scrollwheel: true,
zoomControl: false,
scaleControl: true,
streetViewControl: false,
fullscreenControl: false,
mapTypeControl: false
});
// Create the search box and link it to the UI element.
var input = document.getElementById('pac-input');
var searchBox = new google.maps.places.SearchBox(input);
map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
// Bias the SearchBox results towards current map's viewport.
map.addListener('bounds_changed', function () {
searchBox.setBounds(map.getBounds());
});
var markers = [];
// Listen for the event fired when the user selects a prediction and retrieve
// more details for that place.
searchBox.addListener('places_changed', function () {
var places = searchBox.getPlaces();
if (places.length == 0) {
return;
}
// Clear out the old markers.
markers.forEach(function (marker) {
marker.setMap(null);
});
markers = [];
// For each place, get the icon, name and location.
var bounds = new google.maps.LatLngBounds();
places.forEach(function (place) {
if (!place.geometry) {
console.log("Returned place contains no geometry");
return;
}
// create infowindow: just while debugging not needed in View
var infowindow = new google.maps.InfoWindow();
// create geocoder for address
var geocoder = new google.maps.Geocoder();
// Create a marker for each place.
markers.push(new google.maps.Marker({
map: map,
//icon: "/Content/icons/01.png",
title: place.name,
position: place.geometry.location,
draggable: true
}));
// Add listeners to marker:
// click: opens infowindow
markers[0].addListener('click', function () {
infowindow.open(map, markers[0]);
infowindow.setContent(place.name + ': ' + place.geometry.location);
infowindow.open(map, this);
// Add listeners to map
google.maps.event.addListener(markers[0], 'dragend', function (evt) {
infowindow.setContent('Lat: ' + evt.latLng.lat() + ' Lng: ' + evt.latLng.lng());
infowindow.open(map, this);
map.setCenter(markers[0].getPosition());
markers[0].setMap(map);
map.setTilt(0);
map.setZoom(20);
// update return values
// gLat, gLong, gAddr are global variables
gLat = evt.latLng.lat();
gLong = evt.latLng.lng();
// get address
var latlng = { lat: parseFloat(gLat), lng: parseFloat(gLong) };
geocoder.geocode({ 'location': latlng }, function (results, status) {
if (status === 'OK') {
if (results[0]) { gAddr = results[0].formatted_address } else {
gAddr = 'NotFound';
}
}
});
});
});
if (place.geometry.viewport) {
// Only geocodes have viewport.
bounds.union(place.geometry.viewport);
} else {
bounds.extend(place.geometry.location);
}
});
map.fitBounds(bounds);
});
}
</script>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Chiudi</button>
<button type="button" class="btn btn-primary" onclick="updFields(gLat, gLong, gAddr)">Salva</button>
</div>
</div>
</div>
</div>
}
<script>
$('#findInModal').on('show.bs.modal', function () {
})
function updFields(lat,lng, addr) {
//alert('Lat: ' + lat + '\nLng: ' + lng + '\nAddr: ' + addr);
//document.getElementById("Address").value = addr;
//document.getElementById("Latitude").value = lat;
//document.getElementById("Longitude").value = lng;
$('#Address').val(addr);
$('#Latitude').val(lat);
$('#Longitude').val(lng);
}
</script>
infowindow和警报只是在开发过程中,但不是最终解决方案的一部分。
基本上我实现了一个带有Autocomplete和Place服务的Google Maps Search Box,以及一个Geocoder来从协调器中检索地址。为此,我添加了一个更新隐藏字段的函数。视图的代码要复杂得多,因为它包含其他字段与地图中的位置无关,并且可以手动修改字段,但基本上这是代码的主干。
我想发布图片,似乎我的APIkey已超过配额。