Javascript 未捕获类型错误:无法读取属性';setProperty';未定义的

Javascript 未捕获类型错误:无法读取属性';setProperty';未定义的,javascript,json,google-maps,google-maps-api-3,Javascript,Json,Google Maps,Google Maps Api 3,我试图在互联网上找到这个问题的答案。我找到了一个,但似乎没有人能给出正确的答案 我正在尝试谷歌地图API网站上的一个例子。为了使用不同国家的人口普查数据,我只对您的代码做了一些更改 我更改了链接,以便它可以访问我自己的json文件。在region.geojson中,您拥有土耳其各省的所有坐标;在test.json中,您拥有每个省份的人口普查数据 我将普查数据放在相同的格式中,但当loadCensusData函数点击时 地图数据 .getFeatureById(stateId) .setPrope

我试图在互联网上找到这个问题的答案。我找到了一个,但似乎没有人能给出正确的答案

  • 我正在尝试谷歌地图API网站上的一个例子。为了使用不同国家的人口普查数据,我只对您的代码做了一些更改
  • 我更改了链接,以便它可以访问我自己的json文件。在region.geojson中,您拥有土耳其各省的所有坐标;在test.json中,您拥有每个省份的人口普查数据
  • 我将普查数据放在相同的格式中,但当loadCensusData函数点击时
    地图数据 .getFeatureById(stateId) .setProperty(“普查变量”,普查变量) 迭代时,它会给我以下错误,“UncaughtTypeError:无法读取未定义的属性'setProperty'。 如果我对此进行注释,它将继续迭代直到结束,但问题是我将无法使用“census_variable”,因为它尚未设置。 4.如果我改变链接指向美国人口普查数据,它会像预期的那样再次发挥作用

    有没有办法解决这个错误?或者你知道这是什么原因吗

    请参见下面我的地图代码:

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
        <title>Mashups with google.maps.Data</title>
        <style>
          html, body, #map { height: 100%; margin: 0; padding: 0; overflow: hidden; }
            .nicebox {
              position: absolute;
              text-align: center;
              font-family: "Roboto", "Arial", sans-serif;
              font-size: 13px;
              z-index: 5;
              box-shadow: 0 4px 6px -4px #333;
              padding: 5px 10px;
              background: rgb(255,255,255);
              background: linear-gradient(to bottom,rgba(255,255,255,1) 0%,rgba(245,245,245,1) 100%);
              border: rgb(229, 229, 229) 1px solid;
            }
            #controls {
              top: 10px;
              left: 110px;
              width: 360px;
              height: 45px;
            }
            #data-box {
              top: 10px;
              left: 500px;
              height: 45px;
              line-height: 45px;
              display: none;
            }
            #census-variable {
              width: 360px;
              height: 20px;
            }
            #legend { display: flex; display: -webkit-box; padding-top: 7px }
            .color-key {
              background: linear-gradient(to right,
                hsl(5, 69%, 54%) 0%,
                hsl(29, 71%, 51%) 17%,
                hsl(54, 74%, 47%) 33%,
                hsl(78, 76%, 44%) 50%,
                hsl(102, 78%, 41%) 67%,
                hsl(127, 81%, 37%) 83%,
                hsl(151, 83%, 34%) 100%);
              flex: 1;
              -webkit-box-flex: 1;
              margin: 0 5px;
              text-align: left;
              font-size: 1.0em;
              line-height: 1.0em;
            }
            #data-value { font-size: 2.0em; font-weight: bold }
            #data-label { font-size: 2.0em; font-weight: normal; padding-right: 10px; }
            #data-label:after { content: ':' }
            #data-caret { margin-left: -5px; display: none; font-size: 14px; width: 14px}
        </style>
      </head>
      <body>
        <div id="controls" class="nicebox">
          <div>
          <select id="census-variable">
            <option value="test">Fertility rate 2015</option>
            <option value="https://storage.googleapis.com/mapsdevsite/json/DP05_0017E">Median age</option>
          </select>
          </div>
          <div id="legend">
            <div id="census-min">min</div>
            <div class="color-key"><span id="data-caret">&#x25c6;</span></div>
            <div id="census-max">max</div>
          </div>
        </div>
        <div id="data-box" class="nicebox">
          <label id="data-label" for="data-value"></label>
          <span id="data-value"></span>
        </div>
        <div id="map"></div>
        <script>
          var mapStyle = [{
            'stylers': [{'visibility': 'off'}]
          }, {
            'featureType': 'landscape',
            'elementType': 'geometry',
            'stylers': [{'visibility': 'on'}, {'color': '#fcfcfc'}]
          }, {
            'featureType': 'water',
            'elementType': 'geometry',
            'stylers': [{'visibility': 'on'}, {'color': '#bfd4ff'}]
          }];
          var map;
          var censusMin = Number.MAX_VALUE, censusMax = -Number.MAX_VALUE;
    
          function initMap() {
    
            // load the map
            map = new google.maps.Map(document.getElementById('map'), {
              center: {lat: 40, lng: -100},
              zoom: 4,
              styles: mapStyle
            });
    
    
            // set up the style rules and events for google.maps.Data
            map.data.setStyle(styleFeature);
            map.data.addListener('mouseover', mouseInToRegion);
            map.data.addListener('mouseout', mouseOutOfRegion);
    
            // wire up the button
            var selectBox = document.getElementById('census-variable');
            google.maps.event.addDomListener(selectBox, 'change', function() {
              clearCensusData();
              loadCensusData(selectBox.options[selectBox.selectedIndex].value);
            });
    
            // state polygons only need to be loaded once, do them now
            loadMapShapes();
    
          }
    
          /** Loads the state boundary polygons from a GeoJSON source. */
          function loadMapShapes() {
            // load US state outline polygons from a GeoJson file
            map.data.loadGeoJson('region.geojson', { idPropertyName: 'meso:name_local' });
    
            // wait for the request to complete by listening for the first feature to be
            // added
            google.maps.event.addListenerOnce(map.data, 'addfeature', function() {
              google.maps.event.trigger(document.getElementById('census-variable'),
                  'change');
            });
          }
    
          /**
           * Loads the census data from a simulated API call to the US Census API.
           *
           * @param {string} variable
           */
          function loadCensusData(variable) {
            // load the requested variable from the census API (using local copies)
            var xhr = new XMLHttpRequest();
            xhr.open('GET', variable + '.json');
            xhr.onload = function() {
              var censusData = JSON.parse(xhr.responseText);
              censusData.shift(); // the first row contains column names
              censusData.forEach(function(row) {
                var censusVariable = parseFloat(row[0]);
                var stateId = row[1];
                console.log('StateId row[0] '+censusVariable);
                console.log('censusVariable row[1] '+stateId);
    
                // keep track of min and max values
                if (censusVariable < censusMin) {
                  censusMin = censusVariable;
                }
                if (censusVariable > censusMax) {
                  censusMax = censusVariable;
                }
    
                // update the existing row with the new data
                map.data
                  .getFeatureById(stateId)
                  .setProperty('census_variable');
              });
    
              // update and display the legend
              document.getElementById('census-min').textContent =
                  censusMin.toLocaleString();
              document.getElementById('census-max').textContent =
                  censusMax.toLocaleString();
            };
            xhr.send();
          }
    
          /** Removes census data from each shape on the map and resets the UI. */
          function clearCensusData() {
            censusMin = Number.MAX_VALUE;
            censusMax = -Number.MAX_VALUE;
            map.data.forEach(function(row) {
              row.setProperty('census_variable', undefined);
            });
            document.getElementById('data-box').style.display = 'none';
            document.getElementById('data-caret').style.display = 'none';
          }
    
          /**
           * Applies a gradient style based on the 'census_variable' column.
           * This is the callback passed to data.setStyle() and is called for each row in
           * the data set.  Check out the docs for Data.StylingFunction.
           *
           * @param {google.maps.Data.Feature} feature
           */
          function styleFeature(feature) {
            var low = [5, 69, 54];  // color of smallest datum
            var high = [151, 83, 34];   // color of largest datum
    
            // delta represents where the value sits between the min and max
            var delta = (feature.getProperty('census_variable') - censusMin) /
                (censusMax - censusMin);
    
            var color = [];
            for (var i = 0; i < 3; i++) {
              // calculate an integer color based on the delta
              color[i] = (high[i] - low[i]) * delta + low[i];
            }
    
            // determine whether to show this shape or not
            var showRow = true;
            if (feature.getProperty('census_variable') == null ||
                isNaN(feature.getProperty('census_variable'))) {
              showRow = false;
            }
    
            var outlineWeight = 0.5, zIndex = 1;
            if (feature.getProperty('state') === 'hover') {
              outlineWeight = zIndex = 2;
            }
    
            return {
              strokeWeight: outlineWeight,
              strokeColor: '#fff',
              zIndex: zIndex,
              fillColor: 'hsl(' + color[0] + ',' + color[1] + '%,' + color[2] + '%)',
              fillOpacity: 0.75,
              visible: showRow
            };
          }
    
          /**
           * Responds to the mouse-in event on a map shape (state).
           *
           * @param {?google.maps.MouseEvent} e
           */
          function mouseInToRegion(e) {
            // set the hover state so the setStyle function can change the border
            e.feature.setProperty('state', 'hover');
    
            var percent = (e.feature.getProperty('census_variable') - censusMin) /
                (censusMax - censusMin) * 100;
    
            // update the label
            document.getElementById('data-label').textContent =
                e.feature.getProperty('NAME');
            document.getElementById('data-value').textContent =
                e.feature.getProperty('census_variable').toLocaleString();
            document.getElementById('data-box').style.display = 'block';
            document.getElementById('data-caret').style.display = 'block';
            document.getElementById('data-caret').style.paddingLeft = percent + '%';
          }
    
          /**
           * Responds to the mouse-out event on a map shape (state).
           *
           * @param {?google.maps.MouseEvent} e
           */
          function mouseOutOfRegion(e) {
            // reset the hover state, returning the border to normal
            e.feature.setProperty('state', 'normal');
          }
    
        </script>
        <script async defer
            src="https://maps.googleapis.com/maps/api/js?key=API_KEY&callback=initMap">
        </script>
      </body>
    </html>
    

    另一个包含所有geoJSON数据的文件太大,无法在这里发布。但如果有必要,我可以找到一种方法与您分享。

    我终于找到了答案。坦率地说,这是我犯的一个相当愚蠢的错误。我想我已经很累了,没有意识到我的错误,所以我要感谢所有对我的问题发表评论的人,因为这帮助我意识到我做错了什么

    有两个JSON文件。一个包含坐标,我们称之为坐标.geojson,另一个包含普查数据,我们称之为普查.json

    现在让这些代码行开始工作

    map.data
         .getFeatureById(stateId)
         .setProperty('census_variable');
    
    您必须确保stateId与普查.json文件中的id以及坐标.geojson文件中的id都对应

    在我的例子中,census.json文件中的stateId不等于coordinates.geojson中的第一个id/state,它是Aydin。然而,census.json是从Adana开始的,然后是Adıyaman等

    因此,我不得不将人口普查数据的顺序更改为

    [["DP02_0066PE","region"],
    ["1.85", "Aydin"],
    ["1.72", "Izmir"],
    ["1.64", "Balikesir"],
    ["1.53", "Çanakkale"],
    ["1.53", "Edirne"],
    ["1.54", "Kirklareli"],
    ["1.93", "Tekirdag"],
    ["1.71", "Bilecik"],
    ["1.91", "Bursa"],
    ["1.88", "Istanbul"],
    ["2.06", "Kocaeli"],
    ["1.92", "Sakarya"],
    ["1.59", "Bolu"],
    ["1.55", "Eskisehir"],
    ["1.62", "Kastamonu"],
    ["1.96", "Antalya"],
    ["2.06", "Afyon"],
    ["1.77", "Burdur"],
    ["1.84", "Denizli"],
    ["1.70", "Isparta"],
    ["1.58", "Kütahya"],
    ["1.92", "Manisa"],
    ["1.75", "Mugla"],
    ["2.86", "Adiyaman"],
    ["1.97", "Elazig"],
    ["2.61", "Kahramanmaras"],
    ["2.01", "Malatya"],
    ["2.15", "Içel"],
    ["1.79", "Kirsehir"],
    ["2.18", "Kayseri"],
    ["1.96", "Nevsehir"],
    ["2.70", "Hatay"],
    ["1.79", "Amasya"],
    ["1.83", "Çorum"],
    ["1.62", "Giresun"],
    ["1.81", "Ordu"],
    ["1.72", "Sinop"],
    ["1.96", "Sivas"],
    ["1.80", "Samsun"],
    ["1.72", "Tokat"],
    ["1.73", "Artvin"],
    ["2.51", "Erzurum"],
    ["1.82", "Erzincan"],
    ["1.78", "Rize"],
    ["1.85", "Trabzon"],
    ["3.80", "Agri"],
    ["2.42", "Bingöl"],
    ["3.21", "Diyarbakir"],
    ["3.45", "Mus"],
    ["3.40", "Bitlis"],
    ["1.76", "Ankara"],
    ["1.77", "Çankiri"],
    ["1.55", "Zonguldak"],
    ["2.18", "Konya"],
    ["2.10", "Karaman"],
    ["1.73", "Usak"],
    ["3.15", "Gaziantep"],
    ["4.38", "Sanliurfa"],
    ["2.31", "Adana"],
    ["1.71", "Kirikkale"],
    ["2.18", "Nigde"],
    ["2.24", "Aksaray"],
    ["1.99", "Yozgat"],
    ["1.66", "Gümüshane"],
    ["2.07", "Bayburt"],
    ["2.64", "Kars"],
    ["3.41", "Mardin"],
    ["3.24", "Batman"],
    ["3.55", "Siirt"],
    ["4.01", "Sirnak"],
    ["1.69", "Tunceli"],
    ["2.69", "Hakkari"],
    ["3.36", "Van"],
    ["2.15", "Ardahan"],
    ["3.04", "Igdir"],
    ["2.92", "Kilis"],
    ["2.47", "Osmaniye"],
    ["1.77", "Yalova"],
    ["1.85", "Düzce"],
    ["1.56", "Karabük"],
    ["1.58", "Bartin"]]
    
    最后但并非最不重要的一点是,请注意,我删除了所有特定的土耳其字符,如ğ、ı和ş,因为id来自坐标.geojson,其中没有它们。因此,我将Ağrı改为Agri等等

    我想如果我用数字作为ID而不是名字会更好


    我希望这将防止其他人犯同样的错误。

    您的问题是这些函数中没有检查空值的错误。然而,可能还有更多。只需确保传递给函数的对象具有正在更改的属性。
    map.data.getFeatureById(stateId)
    正在返回未定义的属性可能
    stateId
    不是JSON文件中的id。
    [["DP02_0066PE","region"],
    ["1.85", "Aydin"],
    ["1.72", "Izmir"],
    ["1.64", "Balikesir"],
    ["1.53", "Çanakkale"],
    ["1.53", "Edirne"],
    ["1.54", "Kirklareli"],
    ["1.93", "Tekirdag"],
    ["1.71", "Bilecik"],
    ["1.91", "Bursa"],
    ["1.88", "Istanbul"],
    ["2.06", "Kocaeli"],
    ["1.92", "Sakarya"],
    ["1.59", "Bolu"],
    ["1.55", "Eskisehir"],
    ["1.62", "Kastamonu"],
    ["1.96", "Antalya"],
    ["2.06", "Afyon"],
    ["1.77", "Burdur"],
    ["1.84", "Denizli"],
    ["1.70", "Isparta"],
    ["1.58", "Kütahya"],
    ["1.92", "Manisa"],
    ["1.75", "Mugla"],
    ["2.86", "Adiyaman"],
    ["1.97", "Elazig"],
    ["2.61", "Kahramanmaras"],
    ["2.01", "Malatya"],
    ["2.15", "Içel"],
    ["1.79", "Kirsehir"],
    ["2.18", "Kayseri"],
    ["1.96", "Nevsehir"],
    ["2.70", "Hatay"],
    ["1.79", "Amasya"],
    ["1.83", "Çorum"],
    ["1.62", "Giresun"],
    ["1.81", "Ordu"],
    ["1.72", "Sinop"],
    ["1.96", "Sivas"],
    ["1.80", "Samsun"],
    ["1.72", "Tokat"],
    ["1.73", "Artvin"],
    ["2.51", "Erzurum"],
    ["1.82", "Erzincan"],
    ["1.78", "Rize"],
    ["1.85", "Trabzon"],
    ["3.80", "Agri"],
    ["2.42", "Bingöl"],
    ["3.21", "Diyarbakir"],
    ["3.45", "Mus"],
    ["3.40", "Bitlis"],
    ["1.76", "Ankara"],
    ["1.77", "Çankiri"],
    ["1.55", "Zonguldak"],
    ["2.18", "Konya"],
    ["2.10", "Karaman"],
    ["1.73", "Usak"],
    ["3.15", "Gaziantep"],
    ["4.38", "Sanliurfa"],
    ["2.31", "Adana"],
    ["1.71", "Kirikkale"],
    ["2.18", "Nigde"],
    ["2.24", "Aksaray"],
    ["1.99", "Yozgat"],
    ["1.66", "Gümüshane"],
    ["2.07", "Bayburt"],
    ["2.64", "Kars"],
    ["3.41", "Mardin"],
    ["3.24", "Batman"],
    ["3.55", "Siirt"],
    ["4.01", "Sirnak"],
    ["1.69", "Tunceli"],
    ["2.69", "Hakkari"],
    ["3.36", "Van"],
    ["2.15", "Ardahan"],
    ["3.04", "Igdir"],
    ["2.92", "Kilis"],
    ["2.47", "Osmaniye"],
    ["1.77", "Yalova"],
    ["1.85", "Düzce"],
    ["1.56", "Karabük"],
    ["1.58", "Bartin"]]