Получить положение с модальной карты Google в представлении Razor - PullRequest
0 голосов
/ 07 февраля 2019

Я пишу проект MVC, который включает в себя возможность добавлять точки на карту Google.До сих пор я мог добавлять точки в БД путем жесткого кодирования значений широты и долготы, но я хочу позволить пользователю выбрать положение на карте и отправить их обратно в контроллер из представления Razor.Я уже написал часть вида, и я могу открыть модальное всплывающее окно с картой и жестко запрограммированным местоположением.Я хочу сделать следующее: 1. позволить пользователю вставить адрес в текстовое поле 2. открыть модальное всплывающее окно и центрировать карту с маркером рядом с адресом 3. сохранить положение в двух полях представления, чтобыотправьте их обратно в контроллер.

Я использовал код, предоставленный разработчиками Google по адресу: https://developers.google.com/maps/documentation/javascript/examples/place-details, и пришел к следующему коду:

Весь код находится вRazor View:

    <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">&times;</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&region=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 в родительское представление, но предполагается, что они обновят модель => модель. продольная и модель => модель. продольная значений, которые будут возвращены в контроллер для обновления базы данных.

Заранее благодарен за любую помощь.

1 Ответ

0 голосов
/ 07 марта 2019

Никакой помощи от разработчиков, но, углубившись в документацию 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">&times;</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 и оповещения только находятся в процессе разработки, но не являются частью окончательного решения.

По сути, я реализовал окно поиска Google Maps с сервисом автозаполнения и размещения и геокодером для получения адреса изКоординаторы. Для этого я добавил функцию, которая обновляет мои скрытые поля. Код представления намного сложнее, потому что он содержит другие поля, не относящиеся к позиции на карте, и позволяет вручную изменять поля, но в основном этооснова кода.

Я хотел бы опубликовать изображения, похоже, мой API-ключ превысил квоту.

...