【问题标题】:"Uncaught TypeError: marker.getPosition is not a function" when adding Marker Clusterer to Google Map将 Marker Clusterer 添加到 Google Map 时出现“未捕获的 TypeError:marker.getPosition 不是函数”
【发布时间】:2018-07-13 01:13:34
【问题描述】:

我已经使用数据库中的自定义标记构建了一个谷歌地图,效果很好。工作版本可以在here找到。

因为将来会有更多标记,所以我尝试向地图添加标记聚类器,但它在 Google 开发者控制台中出现错误:

未捕获的类型错误:marker.getPosition 不是函数

抛出错误的版本可以在here找到。

这是我的 maptest_so.php 的样子:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <title>KaiPai | Gutes Essen</title>
    <!-- Bootstrap core CSS -->
    <link href="assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
    <!-- Custom Styles -->
    <link href="assets/map.css" rel="stylesheet">
  </head>

  <body>
    <!-- Navigation -->
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
      <div class="container">
        <a class="navbar-brand" href="index.php">
        <img src="img/logo.png" width="85" height="25" alt="KaiPai">
        </a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarResponsive">
          <ul class="navbar-nav mr-auto">
            <li class="nav-item">
              <a class="nav-link" href="index.php">Startseite
              </a>
            </li>
            <li class="nav-item active">
              <a class="nav-link" href="map.php">Karte</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="about.php">Über KaiPai</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="commitement.php">Ethik & Essen</a>
            </li>
          </ul>
          <ul class="navbar-nav">
            <li class="nav-item">
              <a class="nav-link" href="admin/admin.php">Administration
              </a>
            </li>
          </ul>
        </div>
      </div>
    </nav>
<!-- Page Content -->
<div class="map" id="map"></div>

<!-- Custom Marker Icons -->
<script type="text/javascript">
    var iconBase = 'https://www.kaipai.de/img/customMapIcons/';
    var icons = {
      1: {
      name: 'Backwaren',
      icon: iconBase + 'bakery.png'
      },
      2: {
      name: 'Getränke',
      icon: iconBase + 'beverages.png'
      },
      3: {
      name: 'Fisch',
      icon: iconBase + 'fish.png'
      },
      4: {
      name: 'Früchte / Obst',
      icon: iconBase + 'fruit.png'
      },
      5: {
      name: 'Fleisch',
      icon: iconBase + 'meat.png'
      },
      6: {
      name: 'Sonstiges',
      icon: iconBase + 'other.png'
      },
      7: {
      name: 'Restaurant',
      icon: iconBase + 'restaurant.png'
      },
      8: {
      name: 'Supermarkt',
      icon: iconBase + 'supermarket.png'
      }
      };

    // Google Map initialisieren
    function initMap() {
      var map = new google.maps.Map(document.getElementById('map'), {
      center: new google.maps.LatLng(53.5508, 9.9928),
      zoom: 11,
    });

    var infoWindow = new google.maps.InfoWindow;

      // Marker aus XML Datei erstellen
      downloadUrl('genxml.php', function(data) {
        var xml = data.responseXML;
        var markers = xml.documentElement.getElementsByTagName('marker');
        var markerCluster = new MarkerClusterer(map, markers,
          {imagePath: 'https://www.kaipai.de/img/markerClustererImages/m'});
        Array.prototype.forEach.call(markers, function(markerElem) {
          var CustomerID = markerElem.getAttribute('CustomerID');
          var CustomerGroupID = markerElem.getAttribute('CustomerGroupID');
          var CustomerName = markerElem.getAttribute('CustomerName');
          var CustomerCity = markerElem.getAttribute('CustomerCity');
          var CustomerCountry = markerElem.getAttribute('CustomerCountry');
          var CustomerStreetName = markerElem.getAttribute('CustomerStreetName');
          var CustomerStreetNumber = markerElem.getAttribute('CustomerStreetNumber');
          var CustomerPostalCode = markerElem.getAttribute('CustomerPostalCode');
          var CustomerPhone = markerElem.getAttribute('CustomerPhone');
          var CustomerFax = markerElem.getAttribute('CustomerFax');
          var CustomerMail = markerElem.getAttribute('CustomerMail');
          var CustomerWeb = markerElem.getAttribute('CustomerWeb');
          var CustomerDescription = markerElem.getAttribute('CustomerDescription');
          var CustomerGroupName = markerElem.getAttribute('CustomerGroupName');
          var TypeName = markerElem.getAttribute('TypeName');
          var TypeID = markerElem.getAttribute('TypeID');
          var point = new google.maps.LatLng(
            parseFloat(markerElem.getAttribute('CustomerLat')),
            parseFloat(markerElem.getAttribute('CustomerLng')));
          // Inhalt des InfoWindow
          var infowincontent = document.createElement('div');
          var header = document.createElement('h5');
            header.textContent = CustomerName
            infowincontent.appendChild(header);
          var street = document.createElement('text');
            street.textContent = CustomerStreetName + ' '
            infowincontent.appendChild(street);
          var number = document.createElement('text');
            number.textContent = CustomerStreetNumber
            infowincontent.appendChild(number);
            infowincontent.appendChild(document.createElement('br'));
          var plz = document.createElement('text');
            plz.textContent = CustomerPostalCode + ' '
            infowincontent.appendChild(plz);
          var city = document.createElement('text');
            city.textContent = CustomerCity
            infowincontent.appendChild(city);
            infowincontent.appendChild(document.createElement('br'));
            infowincontent.appendChild(document.createElement('br'));
          var phone = document.createElement('text');
            phone.textContent = 'Tel: ' + CustomerPhone
            infowincontent.appendChild(phone);
            infowincontent.appendChild(document.createElement('br'));
          var fax = document.createElement('text');
            fax.textContent = 'Fax: ' + CustomerFax
            infowincontent.appendChild(fax);
            infowincontent.appendChild(document.createElement('br'));
          var mail = document.createElement('text');
            mail.textContent = CustomerMail
            infowincontent.appendChild(mail);
            infowincontent.appendChild(document.createElement('br'));
          var web = document.createElement('text');
            web.textContent = CustomerWeb
            infowincontent.appendChild(web);
            infowincontent.appendChild(document.createElement('br'));
            infowincontent.appendChild(document.createElement('br'));
          var routeLink = document.createElement('a');
          var routeLinkText = document.createTextNode("Route in Google Maps planen");
            routeLink.appendChild(routeLinkText);
            routeLink.title = 'Route in Google Maps planen';
            routeLink.target = '_blank'
            routeLink.href = 'https://maps.google.com/maps?daddr=' + CustomerStreetName + '+' + CustomerStreetNumber + '+' + CustomerPostalCode + '+' + CustomerCity
            infowincontent.appendChild(routeLink);
          var icon = icons[TypeID] || {};
          var marker = new google.maps.Marker({
            map: map,
            position: point,
            icon: icons[TypeID].icon
          });

          // Marker Click Event erzeugen
          marker.addListener('click', function() {
            infoWindow.setContent(infowincontent);
            infoWindow.open(map, marker);
          });
        });
      });
    }

  function downloadUrl(url, callback) {
    var request = window.ActiveXObject ?
        new ActiveXObject('Microsoft.XMLHTTP') :
        new XMLHttpRequest;

    request.onreadystatechange = function() {
      if (request.readyState == 4) {
        request.onreadystatechange = doNothing;
        callback(request, request.status);
      }
    };

    request.open('GET', url, true);
    request.send(null);
  }

  function doNothing() {}
</script>
<!-- Google Maps JavaScript API -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAUBsRd-k9I9BjQdiUmKqeQEHYBQIxUfV4&callback=initMap">
</script>
<!-- Google Maps Marker Clusterer -->
<script src="https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/markerclusterer.js">
</script>


<!-- Bootstrap core JavaScript -->
<script src="assets/jquery/jquery.min.js"></script>
<script src="assets/bootstrap/js/bootstrap.bundle.min.js"></script>

页面加载时出现错误,似乎发生在这里:

var markerCluster = new MarkerClusterer(地图, 标记, {imagePath: 'https://www.kaipai.de/img/markerClustererImages/m'

我已经尝试了this Question 接受的解决方案,但没有成功。我试图在同一个线程中测试第一个答案,但我不完全理解它。

谁能帮我指出正确的方向? 我是 Google Maps Javascript API 和 Webdesign 的新手,所以如果我的问题有点不具体,请不要介意。

提前致谢并致以最诚挚的问候!

【问题讨论】:

  • 如果问题不涉及 PHP,您应该删除 PHP 标签。您还应该让我们知道此代码中的 wherewhen 会引发该错误。不要强迫我们搜索并猜测。
  • 这个赋值之后var markers = xml.documentElement.getElementsByTagName('marker'); 你的markers 变量的值是多少?它是google.maps.Marker 对象的数组吗?

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


【解决方案1】:
  1. 您报告了类似 Uncaught TypeError: marker.getPosition is not a function 之类的错误,而实际上在您的代码中的任何地方都看不到 marker.getPosition。在调试或尝试重现错误时,最好提供自包含的示例代码,以帮助您的开发人员重现问题。 Please read this.

  2. 您的 InfoWindow 构造函数缺少括号,因此请像这样添加它们:

    var infoWindow = new google.maps.InfoWindow(); 
    
  3. 您在 MarkerClusterer 中传递 DOM 元素(准确地说是节点),而实际上您必须传递 Markers 对象,而不是 DOM 元素。换句话说,你不能指望这段代码在你的 markerClusterer 中工作:

    downloadUrl('genxml.php', function(data) {
      var xml = data.responseXML;
      var markers = xml.document.getElementsByTagName('marker');
    
  4. 您提供的代码没有任何带有标签名称标记的 HTML 元素:

    var markers = xml.document.getElementsByTagName('marker');
    

    HTML 中的标记在哪里?

  5. 在脚本结束时,您启动了 Marker 构造函数,但随后调用了(我认为)超出范围的方法;一旦您对代码结构、语法错误和逻辑错误进行了排序,请查看是否在控制台中为标记找到任何错误,并在必要时将您的变量移动到全局范围或相同的词法范围中,以便可以访问它。

不幸的是,我无法完整地重现该问题,因为我缺少应用程序的依赖项和其他部分来更彻底......不过,以上内容应该足以使其正常工作。

【讨论】:

  • MarkerClusterer 源代码多次调用marker.getPosition,我相信这就是产生错误(Uncaught TypeError:marker.getPosition)的地方。 Take a look
  • 我已经查看了您的代码,正如我已经说过的,您不能在 markerClusterer 中传递 DOM 元素。您的 var markers 存储了一个类似数组的对象(HTML 元素或节点),这是不对的。你必须传入 Markers 对象。除此之外,对不起,我不得不重复一遍,你的代码有语法和逻辑错误。请参阅我之前的评论。
  • 我同意,看起来@rolle78hh 没有将Marker 对象数组传递给MarkerClusterer 构造函数。
【解决方案2】:

您正在创建 MarkerClusterer 并使用从您的 xml 文件返回的任何内容填充它。它需要填充实际的google.maps.Marker 对象

将您的 forEach 调用更改为 map 并将其放在您的调用中以创建一个新的 MarkerClusterer 实例,如下所示:

var markerCluster = new MarkerClusterer(
  map, 
  Array.prototype.map.call(markers, function(markerElem) {
    //... all your other code
    var marker = new google.maps.Marker({
            position: point,
            icon: icons[TypeID].icon       
    });
    return marker;

  }
  {imagePath: 'https://www.kaipai.de/img/markerClustererImages/m'}
)

【讨论】:

    猜你喜欢
    • 2020-03-29
    • 2017-06-09
    • 1970-01-01
    • 1970-01-01
    • 2016-01-11
    • 1970-01-01
    • 2014-12-02
    • 2021-11-13
    • 1970-01-01
    相关资源
    最近更新 更多