谷歌Maps Api相当新。我有一个数据数组,我想循环遍历并在地图上绘制。看似相当简单,但我发现的所有多标记教程都相当复杂。

让我们以谷歌网站的数据数组为例:

var locations = [
  ['Bondi Beach', -33.890542, 151.274856, 4],
  ['Coogee Beach', -33.923036, 151.259052, 5],
  ['Cronulla Beach', -34.028249, 151.157507, 3],
  ['Manly Beach', -33.80010128657071, 151.28747820854187, 2],
  ['Maroubra Beach', -33.950198, 151.259302, 1]
];

我只是想绘制所有这些点,并在单击时弹出一个infoWindow来显示名称。


当前回答

异步版本:

<script type="text/javascript">
  function initialize() {
    var locations = [
      ['Bondi Beach', -33.890542, 151.274856, 4],
      ['Coogee Beach', -33.923036, 151.259052, 5],
      ['Cronulla Beach', -34.028249, 151.157507, 3],
      ['Manly Beach', -33.80010128657071, 151.28747820854187, 2],
      ['Maroubra Beach', -33.950198, 151.259302, 1]
    ];

    var map = new google.maps.Map(document.getElementById('map'), {
      zoom: 10,
      center: new google.maps.LatLng(-33.92, 151.25),
      mapTypeId: google.maps.MapTypeId.ROADMAP
    });

    var infowindow = new google.maps.InfoWindow();

    var marker, i;

    for (i = 0; i < locations.length; i++) {  
      marker = new google.maps.Marker({
        position: new google.maps.LatLng(locations[i][1], locations[i][2]),
        map: map
      });

      google.maps.event.addListener(marker, 'click', (function(marker, i) {
        return function() {
          infowindow.setContent(locations[i][0]);
          infowindow.open(map, marker);
        }
      })(marker, i));
    }
}

function loadScript() {
  var script = document.createElement('script');
  script.type = 'text/javascript';
  script.src = 'https://maps.googleapis.com/maps/api/js?v=3.exp&' +
      'callback=initialize';
  document.body.appendChild(script);
}

window.onload = loadScript;
  </script>

其他回答

这是我写的另一个版本来节省地图的空间,它将infowindow指针放在标记的实际纬度和长度上,而在显示infowindow时暂时隐藏标记。

它还取消了标准的“标记”分配,并加快了速度 通过直接将新标记分配给标记创建中的标记数组进行处理。但是请注意,标记和信息窗口都添加了额外的属性,所以这种方法有点不合常规……但那是我!

在这些信息窗口问题中从未提到,标准的信息窗口不是放在标记点的lat和lng上,而是放在标记图像的顶部。标记可见性必须隐藏,否则Maps API将再次将信息窗口锚推回标记图像的顶部。

对“标记”数组中的标记的引用在标记声明后立即创建,用于以后可能需要的任何额外处理任务(隐藏/显示,抓取坐标等)。这样就省去了将标记对象赋值给'marker'的额外步骤,然后将'marker'推到标记数组中…在我的书里有很多不必要的处理。

不管怎样,对信息窗口有不同的看法,希望它能帮助你了解和激励你。

    var locations = [
      ['Bondi Beach', -33.890542, 151.274856, 4],
      ['Coogee Beach', -33.923036, 151.259052, 5],
      ['Cronulla Beach', -34.028249, 151.157507, 3],
      ['Manly Beach', -33.80010128657071, 151.28747820854187, 2],
      ['Maroubra Beach', -33.950198, 151.259302, 1]
    ];
    var map;
    var markers = [];

    function init(){
      map = new google.maps.Map(document.getElementById('map_canvas'), {
        zoom: 10,
        center: new google.maps.LatLng(-33.92, 151.25),
        mapTypeId: google.maps.MapTypeId.ROADMAP
      });

      var num_markers = locations.length;
      for (var i = 0; i < num_markers; i++) {  
        markers[i] = new google.maps.Marker({
          position: {lat:locations[i][1], lng:locations[i][2]},
          map: map,
          html: locations[i][0],
          id: i,
        });

        google.maps.event.addListener(markers[i], 'click', function(){
          var infowindow = new google.maps.InfoWindow({
            id: this.id,
            content:this.html,
            position:this.getPosition()
          });
          google.maps.event.addListenerOnce(infowindow, 'closeclick', function(){
            markers[this.id].setVisible(true);
          });
          this.setVisible(false);
          infowindow.open(map);
        });
      }
    }

google.maps.event.addDomListener(window, 'load', init);

这是一个工作的JSFiddle

额外的注意 您将注意到在给定的谷歌示例数据中,'locations'数组中的第四个位置是一个数字。在这个例子中,你也可以使用这个值作为标记id来代替当前循环的值,这样…

var num_markers = locations.length;
for (var i = 0; i < num_markers; i++) {  
  markers[i] = new google.maps.Marker({
    position: {lat:locations[i][1], lng:locations[i][2]},
    map: map,
    html: locations[i][0],
    id: locations[i][3],
  });
};

来源链接

演示链接

完整的HTML代码

在单击或悬停时显示InfoWindow。 只会显示一个InfoWindow

    <!DOCTYPE html>
    <html>

    <head>
        <style>
            /*  <span class="metadata-marker" style="display: none;" data-region_tag="css"></span>       Set the size of the div element that contains the map */
            #map {
                height: 400px;
                /* The height is 400 pixels */
                width: 100%;
                /* The width is the width of the web page */
            }
        </style>
        <script>
            var map;
            var InforObj = [];
            var centerCords = {
                lat: -25.344,
                lng: 131.036
            };
            var markersOnMap = [{
                    placeName: "Australia (Uluru)",
                    LatLng: [{
                        lat: -25.344,
                        lng: 131.036
                    }]
                },
                {
                    placeName: "Australia (Melbourne)",
                    LatLng: [{
                        lat: -37.852086,
                        lng: 504.985963
                    }]
                },
                {
                    placeName: "Australia (Canberra)",
                    LatLng: [{
                        lat: -35.299085,
                        lng: 509.109615
                    }]
                },
                {
                    placeName: "Australia (Gold Coast)",
                    LatLng: [{
                        lat: -28.013044,
                        lng: 513.425586
                    }]
                },
                {
                    placeName: "Australia (Perth)",
                    LatLng: [{
                        lat: -31.951994,
                        lng: 475.858081
                    }]
                }
            ];

            window.onload = function () {
                initMap();
            };

            function addMarkerInfo() {
                for (var i = 0; i < markersOnMap.length; i++) {
                    var contentString = '<div id="content"><h1>' + markersOnMap[i].placeName +
                        '</h1><p>Lorem ipsum dolor sit amet, vix mutat posse suscipit id, vel ea tantas omittam detraxit.</p></div>';

                    const marker = new google.maps.Marker({
                        position: markersOnMap[i].LatLng[0],
                        map: map
                    });

                    const infowindow = new google.maps.InfoWindow({
                        content: contentString,
                        maxWidth: 200
                    });

                    marker.addListener('click', function () {
                        closeOtherInfo();
                        infowindow.open(marker.get('map'), marker);
                        InforObj[0] = infowindow;
                    });
                    // marker.addListener('mouseover', function () {
                    //     closeOtherInfo();
                    //     infowindow.open(marker.get('map'), marker);
                    //     InforObj[0] = infowindow;
                    // });
                    // marker.addListener('mouseout', function () {
                    //     closeOtherInfo();
                    //     infowindow.close();
                    //     InforObj[0] = infowindow;
                    // });
                }
            }

            function closeOtherInfo() {
                if (InforObj.length > 0) {
                    /* detach the info-window from the marker ... undocumented in the API docs */
                    InforObj[0].set("marker", null);
                    /* and close it */
                    InforObj[0].close();
                    /* blank the array */
                    InforObj.length = 0;
                }
            }

            function initMap() {
                map = new google.maps.Map(document.getElementById('map'), {
                    zoom: 4,
                    center: centerCords
                });
                addMarkerInfo();
            }
        </script>
    </head>

    <body>
        <h3>My Google Maps Demo</h3>
        <!--The div element for the map -->
        <div id="map"></div>

        <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>

    </body>

    </html>

根据Daniel Vassallo的回答,下面是一个以更简单的方式处理闭包问题的版本。

因为所有的标记都有一个单独的InfoWindow,而且JavaScript并不关心你是否给对象添加了额外的属性,你所需要做的就是给标记的属性添加一个InfoWindow,然后调用InfoWindow本身的.open() !

编辑:有了足够的数据,页面加载可能会花费很多时间,因此与其使用标记构造InfoWindow,不如只在需要时进行构造。注意,用于构造InfoWindow的任何数据都必须作为属性(data)追加到Marker。还要注意,在第一次单击事件之后,infoWindow将作为它的标记的属性持久化,因此浏览器不需要不断地重构。

var locations = [
  ['Bondi Beach', -33.890542, 151.274856, 4],
  ['Coogee Beach', -33.923036, 151.259052, 5],
  ['Cronulla Beach', -34.028249, 151.157507, 3],
  ['Manly Beach', -33.80010128657071, 151.28747820854187, 2],
  ['Maroubra Beach', -33.950198, 151.259302, 1]
];

var map = new google.maps.Map(document.getElementById('map'), {
  center: new google.maps.LatLng(-33.92, 151.25)
});

for (i = 0; i < locations.length; i++) {  
  marker = new google.maps.Marker({
    position: new google.maps.LatLng(locations[i][1], locations[i][2]),
    map: map,
    data: {
      name: locations[i][0]
    }
  });
  marker.addListener('click', function() {
    if(!this.infoWindow) {
      this.infoWindow = new google.maps.InfoWindow({
        content: this.data.name;
      });
    }
    this.infoWindow.open(map,this);
  })
}

下面是一个Reactjs中多个标记的例子。

下面是映射组件

import React from 'react';
import PropTypes from 'prop-types';
import { Map, InfoWindow, Marker, GoogleApiWrapper } from 'google-maps-react';

const MapContainer = (props) => {
  const [mapConfigurations, setMapConfigurations] = useState({
    showingInfoWindow: false,
    activeMarker: {},
    selectedPlace: {}
  });

  var points = [
    { lat: 42.02, lng: -77.01 },
    { lat: 42.03, lng: -77.02 },
    { lat: 41.03, lng: -77.04 },
    { lat: 42.05, lng: -77.02 }
  ]
  const onMarkerClick = (newProps, marker) => {};

  if (!props.google) {
    return <div>Loading...</div>;
  }

  return (
    <div className="custom-map-container">
      <Map
        style={{
          minWidth: '200px',
          minHeight: '140px',
          width: '100%',
          height: '100%',
          position: 'relative'
        }}
        initialCenter={{
          lat: 42.39,
          lng: -72.52
        }}
        google={props.google}
        zoom={16}
      >
        {points.map(coordinates => (
          <Marker
            position={{ lat: coordinates.lat, lng: coordinates.lng }}
            onClick={onMarkerClick}
            icon={{
              url: 'https://res.cloudinary.com/mybukka/image/upload/c_scale,r_50,w_30,h_30/v1580550858/yaiwq492u1lwuy2lb9ua.png',
            anchor: new google.maps.Point(32, 32), // eslint-disable-line
            scaledSize: new google.maps.Size(30, 30)  // eslint-disable-line
            }}
            name={name}
          />))}
        <InfoWindow
          marker={mapConfigurations.activeMarker}
          visible={mapConfigurations.showingInfoWindow}
        >
          <div>
            <h1>{mapConfigurations.selectedPlace.name}</h1>
          </div>
        </InfoWindow>
      </Map>
    </div>
  );
};

export default GoogleApiWrapper({
  apiKey: process.env.GOOGLE_API_KEY,
  v: '3'
})(MapContainer);

MapContainer.propTypes = {
  google: PropTypes.shape({}).isRequired,
};

已接受的答案,在ES6中重写:

$(document).ready(() => {
  const mapEl = $('#our_map').get(0); // OR document.getElementById('our_map');

  // Display a map on the page
  const map = new google.maps.Map(mapEl, { mapTypeId: 'roadmap' });

  const buildings = [
    {
      title: 'London Eye, London', 
      coordinates: [51.503454, -0.119562],
      info: 'carousel'
    },
    {
      title: 'Palace of Westminster, London', 
      coordinates: [51.499633, -0.124755],
      info: 'palace'
    }
  ];

  placeBuildingsOnMap(buildings, map);
});


const placeBuildingsOnMap = (buildings, map) => {
  // Loop through our array of buildings & place each one on the map  
  const bounds = new google.maps.LatLngBounds();
  buildings.forEach((building) => {
    const position = { lat: building.coordinates[0], lng: building.coordinates[1] }
    // Stretch our bounds to the newly found marker position
    bounds.extend(position);

    const marker = new google.maps.Marker({
      position: position,
      map: map,
      title: building.title
    });

    const infoWindow = new google.maps.InfoWindow();
    // Allow each marker to have an info window
    google.maps.event.addListener(marker, 'click', () => {
      infoWindow.setContent(building.info);
      infoWindow.open(map, marker);
    })

    // Automatically center the map fitting all markers on the screen
    map.fitBounds(bounds);
  })
})