具有双重InfoWindow的双地图标记

时间:2018-03-18 13:28:40

标签: javascript google-maps google-maps-api-3

我有两个谷歌地图自动完成输入,用于两个位置搜索。我也能够在这两个地方管理2个标记。但是我还有一个用于输入名称(用户名)的名称。该名称应显示在两个标记的信息。但是一个标记显示infoWindow而另一个标记显示没有窗口。显示infoWindow的标记没有显示用户名。

以下是我的HTML代码

<div class="pac-card" id="pac-card">
  <div id="pac-container">
    <input id="pac-input" type="text" placeholder="StateSide Guess">
    <input id="pac-input2" type="text" placeholder="Foreign Guess">
  </div>
  <div>
    <form action="" class="guess-submit" style="text-align: center">
        <input type="text" id="name" name="name" placeholder="Your Name" />
        <input type="hidden" id="state" name="state" />
        <input type="hidden" id="stateLat" name="stateLat" />
        <input type="hidden" id="stateLng" name="stateLng" />

        <input type="hidden" id="foreign" name="foreign" />
        <input type="hidden" id="foreignLat" name="foreignLat" />
        <input type="hidden" id="foreignLng" name="foreignLng" />  
        <input type="submit" id="submit" class="btn btn-primary" value="submit" />
    </form>  
  </div>
</div>
<div id="map"></div>
<div id="infowindow-content">
  <img src="" width="16" height="16" id="place-icon">
  <span id="place-name"  class="title"></span><br>
  <span id="place-address"></span>
</div>
<div id="infowindow-content2">
  <img src="" width="16" height="16" id="place-icon2">
  <span id="place-name2"  class="title"></span><br>
  <span id="place-address2"></span>
</div>

<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCqa9_oFYP4yorGy17BILIALjiqKXByoeE&libraries=places&callback=initMap"
    async defer></script>

以下是javascript代码

function initMap() {
  var map = new google.maps.Map(document.getElementById('map'), {
      center: {
          lat: 59.325,
          lng: 18.070
      },
      zoom: 9
  });
  var card    = document.getElementById('pac-card');
  var input   = document.getElementById('pac-input');
  var input2  = document.getElementById('pac-input2');

  var username    = document.getElementById('name').value;

  map.controls[google.maps.ControlPosition.TOP_RIGHT].push(card);

  var autocomplete = new google.maps.places.Autocomplete(input);
  var autocomplete2 = new google.maps.places.Autocomplete(input2);

  autocomplete.bindTo('bounds', map);
  autocomplete2.bindTo('bounds', map);

  var infowindow = new google.maps.InfoWindow();
  var infowindowContent = document.getElementById('infowindow-content');
  var infowindowContent2 = document.getElementById('infowindow-content2');
  infowindow.setContent(infowindowContent);
  var marker = new google.maps.Marker({
      map: map,
      position: {
          lat: 59.325,
          lng: 18.070
      },
      anchorPoint: new google.maps.Point(0, -29)
  });
  var marker2 = new google.maps.Marker({
      map: map,
      position: {
          lat: 50.325,
          lng: 24.070
      },
      anchorPoint: new google.maps.Point(0, -29)
  });

  autocomplete2.addListener('place_changed', function() {
      infowindow.close();
      marker2.setVisible(false);
      var place2 = autocomplete2.getPlace();
      document.getElementById('foreign').value = place2.name;
      document.getElementById('foreignLat').value = place2.geometry.location.lat();
      document.getElementById('foreignLng').value = place2.geometry.location.lng();


      if (place2.geometry.viewport) {
          map.fitBounds(place2.geometry.viewport);
      } else {
          map.setCenter(place2.geometry.location);
          map.setZoom(9);
      }
      marker2.setPosition(place2.geometry.location);
      marker2.setVisible(true);

      infowindowContent2.children['place-name2'].textContent = username;
      infowindow.open(map, marker2);
  });

  autocomplete.addListener('place_changed', function() {
      infowindow.close();
      marker.setVisible(false);
      var place = autocomplete.getPlace();
      document.getElementById('state').value = place.name;
      document.getElementById('stateLat').value = place.geometry.location.lat();
      document.getElementById('stateLng').value = place.geometry.location.lng();

      if (place.geometry.viewport) {
          map.fitBounds(place.geometry.viewport);
      } else {
          map.setCenter(place.geometry.location);
          map.setZoom(9);
      }
      marker.setPosition(place.geometry.location);
      marker.setVisible(true);

      infowindowContent.children['place-name'].textContent = username;
      infowindow.open(map, marker);
  });
}

以下是截图

Google Map Error

3 个答案:

答案 0 :(得分:0)

这是一个可能的解决方案。在autocomplete.addListener回调结束时,添加以下行:

var username = document.getElementById('name').value;
infowindowContent.children['place-name'].textContent = username;
infowindow.setContent(infowindowContent.innerHTML);
infowindow.open(map, marker);

如果您输入名称然后搜索地点,这将有效。

这是JSBin with a working example

答案 1 :(得分:0)

您正在填写username变量之前用户输入信息。

解决方案:在需要时(在自动完成回调函数中)获取它:

autocomplete.addListener('place_changed', function() {
    infowindow.close();
    marker.setVisible(false);
    var place = autocomplete.getPlace();
    document.getElementById('state').value = place.name;
    document.getElementById('stateLat').value = place.geometry.location.lat();
    document.getElementById('stateLng').value = place.geometry.location.lng();

    if (place.geometry.viewport) {
        map.fitBounds(place.geometry.viewport);
    } else {
        map.setCenter(place.geometry.location);
        map.setZoom(9);
    }
    marker.setPosition(place.geometry.location);
    marker.setVisible(true);
    username = document.getElementById('name').value;  // <============= ** get it here **
    infowindowContent.children['place-name'].textContent = username;
    infowindow.open(map, marker);
});

proof of concept fiddle

screenshot of resulting map

代码段

function initMap() {
  var map = new google.maps.Map(document.getElementById('map'), {
    center: {
      lat: 59.325,
      lng: 18.070
    },
    zoom: 3
  });
  var card = document.getElementById('pac-card');
  var input = document.getElementById('pac-input');
  var input2 = document.getElementById('pac-input2');

  var username = document.getElementById('name').value;

  map.controls[google.maps.ControlPosition.TOP_RIGHT].push(card);

  var autocomplete = new google.maps.places.Autocomplete(input);
  var autocomplete2 = new google.maps.places.Autocomplete(input2);

  autocomplete.bindTo('bounds', map);
  autocomplete2.bindTo('bounds', map);

  var infowindow = new google.maps.InfoWindow();
  var infowindowContent = document.getElementById('infowindow-content');
  var infowindowContent2 = document.getElementById('infowindow-content2');
  infowindow.setContent(infowindowContent);
  var marker = new google.maps.Marker({
    map: map,
    position: {
      lat: 59.325,
      lng: 18.070
    },
    anchorPoint: new google.maps.Point(0, -29)
  });
  var marker2 = new google.maps.Marker({
    map: map,
    position: {
      lat: 50.325,
      lng: 24.070
    },
    anchorPoint: new google.maps.Point(0, -29)
  });

  autocomplete2.addListener('place_changed', function() {
    infowindow.close();
    marker2.setVisible(false);
    var place2 = autocomplete2.getPlace();
    document.getElementById('foreign').value = place2.name;
    document.getElementById('foreignLat').value = place2.geometry.location.lat();
    document.getElementById('foreignLng').value = place2.geometry.location.lng();


    if (place2.geometry.viewport) {
      map.fitBounds(place2.geometry.viewport);
    } else {
      map.setCenter(place2.geometry.location);
      map.setZoom(9);
    }
    marker2.setPosition(place2.geometry.location);
    marker2.setVisible(true);
    username = document.getElementById('name').value;
    infowindowContent2.children['place-name2'].textContent = username;
    infowindow.open(map, marker2);
  });

  autocomplete.addListener('place_changed', function() {
    infowindow.close();
    marker.setVisible(false);
    var place = autocomplete.getPlace();
    document.getElementById('state').value = place.name;
    document.getElementById('stateLat').value = place.geometry.location.lat();
    document.getElementById('stateLng').value = place.geometry.location.lng();

    if (place.geometry.viewport) {
      map.fitBounds(place.geometry.viewport);
    } else {
      map.setCenter(place.geometry.location);
      map.setZoom(9);
    }
    marker.setPosition(place.geometry.location);
    marker.setVisible(true);
    username = document.getElementById('name').value;
    infowindowContent.children['place-name'].textContent = username;
    infowindow.open(map, marker);
  });
}
google.maps.event.addDomListener(window, "load", initMap);
html,
body,
#map {
  height: 100%;
  width: 100%;
  margin: 0px;
  padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=places"></script>
<div class="pac-card" id="pac-card">
  <div id="pac-container">
    <input id="pac-input" type="text" placeholder="StateSide Guess">
    <input id="pac-input2" type="text" placeholder="Foreign Guess">
  </div>
  <div>
    <form action="" class="guess-submit" style="text-align: center">
      <input type="text" id="name" name="name" placeholder="Your Name" value="John Smith" />
      <input type="hidden" id="state" name="state" />
      <input type="hidden" id="stateLat" name="stateLat" />
      <input type="hidden" id="stateLng" name="stateLng" />

      <input type="hidden" id="foreign" name="foreign" />
      <input type="hidden" id="foreignLat" name="foreignLat" />
      <input type="hidden" id="foreignLng" name="foreignLng" />
      <input type="submit" id="submit" class="btn btn-primary" value="submit" />
    </form>
  </div>
</div>
<div id="map"></div>
<div id="infowindow-content">
  <img src="" width="16" height="16" id="place-icon">
  <span id="place-name" class="title"></span><br>
  <span id="place-address"></span>
</div>
<div id="infowindow-content2">
  <img src="" width="16" height="16" id="place-icon2">
  <span id="place-name2" class="title"></span><br>
  <span id="place-address2"></span>
</div>

答案 2 :(得分:0)

在看到似乎有很多重复代码的内容后,我对此的看法略有不同 - 特别是当自动完成时结束功能或多或少相同时。为了实现这一点,我删除了分配给DOM元素的许多ID属性,而是选择了dataset属性,而这些属性可以使用querySelector(All)方法之一进行定位。

我在整个过程中放了几条注释 - 这个方法也可以用于两个以上的位置输入字段,只需在正确的父容器pac-container中添加一个新的这样的输入元素,并为相关的infowindow内容等分配类似的属性等。

无论如何,它在一个无聊的星期天过了一段时间,希望它有用。

<!doctype html>
<html>
    <head>
        <title>Google Maps - two autocomplete</title>
        <meta charset='utf-8' />
        <script async defer src='//maps.googleapis.com/maps/api/js?key=AIzaSyCqa9_oFYP4yorGy17BILIALjiqKXByoeE&libraries=places&callback=initMap'></script>
        <script>
            function initMap(){
                /* some variables */
                var autocomplete;
                var infowindow;
                var marker;
                var options;
                var place;
                var obj;
                var url;
                var img;


                /* DOM elements */
                var oDiv     = document.getElementById('map');
                var oCard    = document.getElementById('pac-card');
                var oColInput= document.querySelectorAll('div#pac-container > input[data-type]');
                var oUsername= document.getElementById('name');



                /* Map initial config */
                options={
                    center: {
                        lat: 59.325,
                        lng: 18.070
                    },
                    zoom: 9                 
                };
                /* the map */
                var map = new google.maps.Map( oDiv, options );

                /*
                    Define objects associated with each of the input elements
                    used for places.

                    Each object created has a reference stored in `obj` which is
                    used as a bound object to the event listener so that each item
                    can be accessed within the listener using `this`
                */
                Array.prototype.slice.call( oColInput ).forEach( function( input ){
                    /* options for the autocomplete service */
                    options={
                        strictBounds: false
                    };

                    /* create the autocomplete object */
                    autocomplete = new google.maps.places.Autocomplete( input, options );
                    autocomplete.bindTo( 'bounds', map );

                    /* create the infowindow bound to this autocomplete object */
                    infowindow = new google.maps.InfoWindow( { maxWidth:320, disableAutoPan:false } );
                    infowindow.setContent( document.querySelector('div.iwin[ data-type="'+input.dataset.type+'" ]') );

                    /* ensure hidden content from infowindow does not alter layout */
                    google.maps.event.addListener( infowindow, 'closeclick', function( event ){
                        this.getContent().style.display='none';
                    }.bind( infowindow ));

                    /* add a marker bound to the autocomplete service */
                    marker=new google.maps.Marker({
                        map: map,
                        position: {
                            lat: parseFloat( input.dataset.lat ),
                            lng: parseFloat( input.dataset.lng )
                        },
                        anchorPoint: new google.maps.Point(0, -29)
                    });

                    /* Marker events */
                    google.maps.event.addListener( marker, 'click', function(e){
                        this.open( map );
                        this.getContent().style.display='block';
                        this.setPosition( e.latLng );
                        this.setOptions( { pixelOffset:new google.maps.Size(0,-32) } );
                    }.bind( infowindow ) );


                    /* 
                        add a reference to each object to our binding object used below
                    */
                    obj={
                        'input':input,
                        'type':input.dataset.type,
                        'marker':marker,
                        'autocomplete':autocomplete,
                        'infowindow':infowindow
                    }



                    /* Listen for changes and do some cool things */
                    autocomplete.addListener('place_changed',function(){
                        /* must have a username value to continue as it should appear on the infowindow */
                        if( oUsername.value=='' ){

                            oUsername.classList.add('warn');

                            setTimeout( function(){
                                this.input.value='';
                                oUsername.classList.remove('warn');
                            }.bind( this ),1500);

                            return;
                        }
                        /* reset existing marker if it exists */
                        this.marker.setVisible( false );
                        this.marker.title='';

                        var oWin=this.infowindow.getContent();
                            oWin.style.display='block';

                        place = this.autocomplete.getPlace();
                        console.info( place );

                        /* find suitable hidden inputs within form - using span as parent */
                        var oSpan=document.querySelector('form > span[ id="'+this.type+'" ]');
                            oSpan.querySelector('input[ data-id="name" ]').value=this.input.value=='' ? '' : place.name;
                            oSpan.querySelector('input[ data-id="lat" ]').value=this.input.value=='' ? '' : place.geometry.location.lat();
                            oSpan.querySelector('input[ data-id="lng" ]').value=this.input.value=='' ? '' : place.geometry.location.lng();

                        if( place.geometry.viewport ) {
                            map.fitBounds( place.geometry.viewport );
                        } else {
                            map.setCenter( place.geometry.location );
                            map.setZoom(9);
                        }

                        this.marker.setPosition( place.geometry.location );
                        this.marker.setVisible( true );
                        this.marker.title=place.name;




                        /* find infowindow content & append new values */
                        oWin.querySelector('span[data-id="user-name"]').innerHTML=oUsername.value;
                        oWin.querySelector('span[data-id="place-name"]').innerHTML=place.name;
                        oWin.querySelector('span[data-id="place-address"]').innerHTML=place.formatted_address;

                        if( oWin.querySelector( 'a[data-id="'+this.type+'"]' ) ) oWin.removeChild( oWin.querySelector( 'a[data-id="'+this.type+'"]' ) );

                        var a=document.createElement('a');
                            a.dataset.id=this.type;
                            a.innerHTML='more...';
                            a.target='_blank';
                            a.href=place.url;

                        oWin.appendChild( a );

                        /* open the infowindow and show new content */
                        this.infowindow.open( map, this.marker );
                    }.bind( obj ));/* bind all the objects */
                });
            }
        </script>
        <style>
            html, body, #map {
                height: 100%;
                height:100vh;
                margin: 0px;
                padding: 0px
            }
            #map{
                width:800px;
                height:600px;
                float:none;
                margin:auto;
            }
            .iwin{/* hidden infowindow content elements */
                display:none;
                width:320px;
                height:240px;
                padding:1rem;
                border:1px solid gray;
                border-radius:1rem;
                box-sizing:border-box;
                font-family:calibri,verdana,arial;
            }
            .iwin > img{
                display:inline-block;
                clear:none;
                margin:0.5rem;
                float:left;
                outline:1px dotted rgba(133,133,133,0.25);
                padding:0.1rem;
                min-width:80px;
                min-height:120px;
            }
            .iwin > span{
                float:left;
                min-width:51%;
                margin:0 auto 0.25rem auto;
                display:inline-block;
                clear:right;
                color:gray;
            }
            .iwin > span[data-id='user-name']{
                font-size:1.25rem;
                font-weight:bold;
                color:green;
            }
            .iwin > span[data-id='place-name']{
                font-size:1rem;
            }
            .iwin > span[data-id='place-address']{
                font-size:0.9rem;
            }
            .iwin > a{
                float:right;
                margin:1rem auto;
                font-size:0.75rem;
            }







            #pac-card{
                width:800px;
                float:none;
                margin:auto;
                padding:1rem;
                border:1px solid gray;
                box-sizing:border-box;
                display:flex;
                justify-content:space-around;
            }
            form{
                display:inline-block;
                clear:none;
                width:100%;
            }

            #pac-card > div {
                box-sizing:border-box;
                background:white;
                clear:none;
                margin:0;
                float:none;
                display:block;
            }
            input[type='text'],
            input[type='submit']{
                padding:1rem;
            }
            input[type='text'],
            #name{
                border:1px solid gray;
            }
            .warn{
                border:1px solid red!important;
                background:rgba(255,0,0,0.25);
                color:white;
            }
            input[value]:not([value=""]) + span:before{
                color:green;
                background:transparent;

                padding:0.25rem;
                clear:none;
                content:'L';
                display:inline-block;

                font-family: arial;
                font-weight:bold;
                font-size:1.5rem;

                -ms-transform: scaleX(-1) rotate(-35deg);
                -webkit-transform: scaleX(-1) rotate(-35deg);
                transform: scaleX(-1) rotate(-35deg);

                z-index:2;
                position:relative;
                left:-28rem!important;
            }

            input[type='submit']{
                text-transform:uppercase;
            }
        </style>
    </head>
    <body>
        <!-- // more or less original html content - less ID attributes but extensive use of dataset attributes // -->


        <div class='pac-card' id='pac-card'>
          <div id='pac-container'>
            <input data-type='stateside' data-lat='59.325' data-lng='18.070' type='text' placeholder='StateSide Guess' value='' />
            <input data-type='foreign' data-lat='50.325' data-lng='24.070' type='text' placeholder='Foreign Guess' value='' />
          </div>
          <div>
            <form class='guess-submit' style='text-align: center'>

                <span id='stateside'>
                    <input type='hidden' data-id='name' name='state' value='' /><span></span>
                    <input type='hidden' data-id='lat' name='stateLat' value='' />
                    <input type='hidden' data-id='lng' name='stateLng' value='' />
                </span>

                <span id='foreign'>
                    <input type='hidden' data-id='name' name='foreign' value='' /><span></span>
                    <input type='hidden' data-id='lat' name='foreignLat' value='' />
                    <input type='hidden' data-id='lng' name='foreignLng' value='' />
                </span>

                <input type='text' id='name' name='name' placeholder='Your Name' />
                <input type='submit' id='submit' class='btn btn-primary' value='submit' />
            </form>  
          </div>
        </div>


        <div id='map'></div>


        <!-- hidden elements - infowindow contents -->
        <div id='win_1' class='iwin' data-type='stateside'>
          <img src='' width='16' height='16' />
          <span data-id='user-name'  class='user'></span>
          <span data-id='place-name'  class='title'></span>
          <br />
          <span data-id='place-address'></span>
        </div>

        <div id='win_2' class='iwin' data-type='foreign'>
          <img src='' width='16' height='16' />
          <span data-id='user-name'  class='user'></span>
          <span data-id='place-name' class='title'></span>
          <br />
          <span data-id='place-address'></span>
        </div>


        <!-- // // -->
    </body>
</html>

Two autocomplete,one map