简体   繁体   English

JS-Google Maps API-标记说明请点击

[英]JS - Google Maps API - Directions on Marker Click

I've been working on the Google Maps API to create a website that geolocates users and shows them where the nearby open/closed cafes are. 我一直在使用Google Maps API创建一个可以对用户进行地理位置定位的网站,并向他们显示附近的开放式/封闭式咖啡馆所在的位置。

I am currently trying to integrate functionality that gives the user directions from their current geolocation to the cafe when a marker is clicked but I am having trouble getting this to work and wondering if anyone could offer any pointers on how to achieve this 我目前正在尝试集成一些功能,这些功能可以在单击标记时为用户提供从当前地理位置到咖啡馆的指导,但是我很难使它正常工作,并且想知道是否有人可以提供有关如何实现此目标的指导

var service, map, pos, infoWindow, google, directionsService, directionsDisplay;


/* create google map & add styling */
function initMap() {

    clicked = null;

    directionsService = new google.maps.DirectionsService;
    directionsDisplay = new google.maps.DirectionsRenderer({
        suppressMarkers: true,
        suppressBicyclingLayer: true
    });
    directionsDisplay.setMap(map);

    var styledMapType = new google.maps.StyledMapType([{"featureType": "all", "elementType": "geometry.fill", "stylers": [{"weight": "2.00"}]}, {"featureType": "all", "elementType": "geometry.stroke", "stylers": [{"color": "#9c9c9c"}]}, {"featureType": "all", "elementType": "labels.text", "stylers": [{"visibility": "on"}]}, {"featureType": "administrative.locality", "elementType": "labels.text.fill", "stylers": [{"color": "#ac8d93"}]}, {"featureType": "landscape", "elementType": "all", "stylers": [{"color": "#f2f2f2"}]}, {"featureType": "landscape", "elementType": "geometry.fill", "stylers": [{"color": "#ffffff"}]}, {"featureType": "landscape.man_made", "elementType": "geometry.fill", "stylers": [{"color": "#ffffff"}]}, {"featureType": "poi", "elementType": "all", "stylers": [{"visibility": "off"}]}, {"featureType": "road", "elementType": "all", "stylers": [{"saturation": -100}, {"lightness": 45}]}, {"featureType": "road", "elementType": "geometry.fill", "stylers": [{"color": "#eeeeee"}]}, {"featureType": "road", "elementType": "labels.text.fill", "stylers": [{"color": "#7b7b7b"}]}, {"featureType": "road", "elementType": "labels.text.stroke", "stylers": [{"color": "#ffffff"}]}, {"featureType": "road.highway", "elementType": "all", "stylers": [{"visibility": "simplified"}]}, {"featureType": "road.arterial", "elementType": "labels.icon", "stylers": [{"visibility": "off"}]}, {"featureType": "transit", "elementType": "all", "stylers": [{"visibility": "off"}]}, {"featureType": "water", "elementType": "all", "stylers": [{"color": "#46bcec"}, {"visibility": "on"}]}, {"featureType": "water", "elementType": "geometry.fill", "stylers": [{"color": "#c8d7d4"}]}, {"featureType": "water", "elementType": "labels.text.fill", "stylers": [{"color": "#070707"}]}, {"featureType": "water", "elementType": "labels.text.stroke", "stylers": [{"color": "#ffffff"}]}],
            {name: 'Styled Map'});
    var chch = {lat: -43.530, lng: 172.646};
    map = new google.maps.Map(document.getElementById('map'), {
        center: chch,
        zoom: 13,
        mapTypeControlOptions: {
            mapTypeIds: ['roadmap', 'satellite', 'hybrid', 'terrain',
                'styled_map']
        }
    });
    map.mapTypes.set('styled_map', styledMapType);
    map.setMapTypeId('styled_map');



    infoWindow = new google.maps.InfoWindow({map: map});

    service = new google.maps.places.PlacesService(map);
    service.nearbySearch({
        location: chch,
        openNow: true && false,
        radius: 5000,
        type: ['cafe']
    }, function (results, status) {
        if (status === google.maps.places.PlacesServiceStatus.OK) {
            for (var i = 0; i < results.length; i++) {
                createMarker(results[i]);
            }
        }
    });

    geolocate();
    initAutocomplete();

}


function createMarker(place) {
    var marker = new google.maps.Marker({
        map: map,
        icon: 'img/greenmarker.svg',
        position: place.geometry.location
    });
    var request = {
        reference: place.reference
    };

    service.getDetails(request, function (place, status) {
        var open = "";

        if (!place.hasOwnProperty('opening_hours')) {
            open += "No open times provided";
            marker.setIcon('img/greymarker.svg');
        } else if (place.opening_hours.open_now === true) {
            open += "We are Open";
        } else {
            open += "We are Closed";
            marker.setIcon('img/redmarker.svg');
        }
        ;


        if (status === google.maps.places.PlacesServiceStatus.OK) {
            var contentStr = '<h5>' + place.name + '</h5><p>' + place.formatted_address;
            if (!!place)
                contentStr += '<br>' + open;

            if (!!place.formatted_phone_number)
                contentStr += '<br>' + place.formatted_phone_number;
            if (!!place.website)
                contentStr += '<br><a target="_blank" href="' + place.website + '">' + place.website + '</a></p>';
        } else {
            var contentStr = "<h5>No Result, status=" + status + "</h5>";
        }
        setupInfowindow(marker, infoWindow, contentStr);

    });

    function setupInfowindow(marker, infoWindow, contentStr) {
        marker.addListener('click', function () {
            infoWindow.setContent(contentStr);
            infoWindow.open(map, this);
        });
    }

    google.maps.event.addListener(marker, 'click', function () {
        clicked = marker.getPosition();
        calculateAndDisplayRoute(directionsService, directionsDisplay, pos, clicked);
        console.log(clicked);

//        clicked = {
//            lat: this.position.lat(),
//            lng: this.position.lng()
//        };
    });
}


function geolocate() {
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(function (position) {

            pos = {
                lat: position.coords.latitude,
                lng: position.coords.longitude
            };
            new google.maps.Marker({
                map: map,
                icon: 'img/cross.svg',
                position: pos
            });

            infoWindow.setPosition(pos);
            infoWindow.setContent('Location found.');

            map.setCenter(pos);
            map.setZoom(14);
        }, function () {
            handleLocationError(true, infoWindow, map.getCenter());
        });
    } else {
        // Browser doesn't support Geolocation
        handleLocationError(false, infoWindow, map.getCenter());
    }
}



function initAutocomplete() {

    // 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;
            }

            var searched = {
                lat: place.geometry.location.lat(),
                lng: place.geometry.location.lng()
            };

            infoWindow.setPosition(searched);
            infoWindow.setContent('Location found.');
            map.setCenter(searched);
            map.setZoom(14);

            // Create a marker for each place.
            markers.push(new google.maps.Marker({
                map: map,
                icon: 'img/cross.svg',
                title: place.name,
                position: place.geometry.location
            }));


            if (place.geometry.viewport) {
                // Only geocodes have viewport.
                bounds.union(place.geometry.viewport);
            } else {
                bounds.extend(place.geometry.location);
            }
        });
    });
}


function calculateAndDisplayRoute(directionsService, directionsDisplay, pos, clicked) {
    directionsService.route({
        origin: pos,
        destination: clicked,
        travelMode: 'BICYCLING'
    }, function (response, status) {
        if (status === 'OK') {
            directionsDisplay.setDirections(response);
        } else {
            window.alert('Directions request failed due to ' + status);
        }
    });
}



//if browser doesn't have geolocation then search box shows
function handleLocationError() {
    $(".input__wrapper").show();
}

here's a link that shows where i'm currently at with this - (for the purposes of this example i've edited the geolocation functionality so that it redirects to the city where the cafes are being gathered from) 这是一个链接,显示了我目前所处的位置 -(在本示例中,我编辑了地理位置功能,以便将其重定向到收集咖啡馆的城市)

any help with this would be greatly appreciated! 任何帮助,将不胜感激!

Two things prevented the code you provided from working: 有两件事使您提供的代码无法正常工作:

  1. you changed the geolocation finding to a static location in the var chch , so the var pos was never set 您将地理位置更改为var chch的静态位置,因此从未设置过var pos
  2. You naver attached the directionsDisplay to any panel. 您没有将directionsDisplay附加到任何面板。 I added 我加了

     <div id="directionsPanel"></div> 

    to the Markup and 到标记和

     directionsDisplay.setPanel(document.getElementById("directionsPanel")); 

    after the .setMap() call .setMap()调用之后

and it turns out, apart from that, your code was already right, the result was just not being displayed anywhere: https://jsfiddle.net/786zeqc7/4/ (You have to scroll the output window using the scrollbar, as the map covers the whole frame, to see the directions below the map container after clicking on a marker) see this updated fiddle with a pretty amateurish column layout for preview purposes: https://jsfiddle.net/786zeqc7/5/ 事实证明,除此之外,您的代码已经正确,结果只是未在任何地方显示: https : //jsfiddle.net/786zeqc7/4/ (您必须使用滚动条滚动输出窗口,因为地图覆盖了整个框架,请在单击标记后查看地图容器下方的方向) ,以预览的目的查看此更新的小提琴,并提供了相当业余的列布局: https : //jsfiddle.net/786zeqc7/5/

some more suggestions going beyond the question: 一些超出问题的建议:

  1. You should check for status === google.maps.DirectionsStatus.OK instead for the string 'OK' - it's very unlikely, but when the API should change the value of that constant, it would break your code. 您应该检查status === google.maps.DirectionsStatus.OK而不是字符串'OK' status === google.maps.DirectionsStatus.OK这是不太可能的,但是当API应该更改该常量的值时,它将破坏您的代码。

  2. there are some more JavaScript errors thrown in the console that you should look into and fix 控制台中还会引发一些JavaScript错误,您应该调查并修复

  3. Use protocoll-less urls for the marker images to make them work in an https environment as well 使用无协议的网址作为标记图片,以使其也可在https环境中使用

  4. You have the var pos in global scope as well as an argument of the function calculateAndDisplayRoute() - that confused me and it probably wil lconfuse you too, when you look at this code again in a couple of months or years. 您拥有全局范围内的var pos以及函数calculateAndDisplayRoute()的参数,这使我感到困惑,当您在几个月或几年后再次查看此代码时,也可能使您感到困惑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM