2017-08-04 52 views
-1

我试图在整个互联网上找到这个问题的答案。我发现一个similar question,但似乎没有人能够给出正确的答案。未捕获TypeError:无法读取undefined属性'setProperty'

  1. 我正在试用Google Maps API网站https://developers.google.com/maps/documentation/javascript/combining-data的一个示例。我只对代码进行了一些更改,以便为不同国家/地区使用人口普查数据。
  2. 我改变了链接,以便它可以访问我自己的json文件。在region.geojson中,您拥有土耳其各省的所有坐标,而在test.json中,您可以获得每个省的人口普查数据。
  3. 我把人口普查数据以相同的格式,但是当loadCensusData功能击中
    map.data .getFeatureById(STATEID) .setProperty( 'census_variable',censusVariable);

while it iterating it给我下面的错误,“未捕获的类型错误:无法读取未定义的属性'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> 

这里是人口普查数据我的JSON文件(test.json):

[["DP02_0066PE","region"], 
["2.31", "Adana"], 
["2.86", "Adıyaman"], 
["2.06", "Afyonkarahisar"], 
["3.80", "Ağrı"], 
["2.24", "Aksaray"], 
["1.79", "Amasya"], 
["1.76", "Ankara"], 
["1.96", "Antalya"], 
["2.15", "Ardahan"], 
["1.73", "Artvin"], 
["1.85", "Aydın"], 
["1.64", "Balıkesir"], 
["1.58", "Bartın"], 
["3.24", "Batman"], 
["2.07", "Bayburt"], 
["1.71", "Bilecik"], 
["2.42", "Bingöl"], 
["3.40", "Bitlis"], 
["1.59", "Bolu"], 
["1.77", "Burdur"], 
["1.91", "Bursa"], 
["1.53", "Çanakkale"], 
["1.77", "Çankırı"], 
["1.83", "Çorum"], 
["1.84", "Denizli"], 
["3.21", "Diyarbakır"], 
["1.85", "Düzce"], 
["1.53", "Edirne"], 
["1.97", "Elazığ"], 
["1.82", "Erzincan"], 
["2.51", "Erzurum"], 
["1.55", "Eskişehir"], 
["3.15", "Gaziantep"], 
["1.62", "Giresun"], 
["1.66", "Gümüşhane"], 
["2.69", "Hakkâri"], 
["2.70", "Hatay"], 
["3.04", "Iğdır"], 
["1.70", "Isparta"], 
["1.88", "İstanbul"], 
["1.72", "İzmir"], 
["2.61", "Kahramanmaraş"], 
["1.56", "Karabük"], 
["2.10", "Karaman"], 
["2.64", "Kars"], 
["1.62", "Kastamonu"], 
["2.18", "Kayseri"], 
["2.92", "Kilis"], 
["1.71", "Kırıkkale"], 
["1.54", "Kırklareli"], 
["1.79", "Kırşehir"], 
["2.06", "Kocaeli"], 
["2.18", "Konya"], 
["1.58", "Kütahya"], 
["2.01", "Malatya"], 
["1.92", "Manisa"], 
["3.41", "Mardin"], 
["2.15", "Mersin"], 
["1.75", "Muğla"], 
["3.45", "Muş"], 
["1.96", "Nevşehir"], 
["2.18", "Niğde"], 
["1.81", "Ordu"], 
["2.47", "Osmaniye"], 
["1.78", "Rize"], 
["1.92", "Sakarya"], 
["1.80", "Samsun"], 
["4.38", "Şanlıurfa"], 
["3.55", "Siirt"], 
["1.72", "Sinop"], 
["4.01", "Şırnak"], 
["1.96", "Sivas"], 
["1.93", "Tekirdağ"], 
["1.72", "Tokat"], 
["1.85", "Trabzon"], 
["1.69", "Tunceli"], 
["1.73", "Uşak"], 
["3.36", "Van"], 
["1.77", "Yalova"], 
["1.99", "Yozgat"], 
["1.55", "Zonguldak"]] 

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

+0

你的问题在这里是没有错误检查这些函数的空值。但是,可能还有更多。只要确保传递给函数的对象具有正在更改的属性。 –

+0

'map.data.getFeatureById(stateId)'正在返回undefined – James

+0

可能'stateId'不是JSON文件中的一个id。 – geocodezip

回答

0

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

有两个JSON文件。一个包含了坐标,让我们把它coordinates.geojson,另一个包含了人口普查数据,让我们把它census.json

现在的代码工作的这些线,

map.data 
    .getFeatureById(stateId) 
    .setProperty('census_variable'); 

你必须确保STATEID同时对应于在census.json文件中的ID以及在该ID coordinates.geojson文件。

在我的情况下STATEID从census.json文件中坐标不等于第一个ID /状态。geojson这是艾登。而census.json开始阿达纳,然后阿迪亚曼等

因此我不得不普查数据的顺序更改为

[["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"]] 

最后但并非最不重要的,请注意,我删除了所有具体的土耳其字符,如»,ı和ş,因为从的坐标编号拼写没有他们。因此我将Ağrı改为Agri等等。

我想如果我用数字作为ID而不是名称,情况会更好。

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

相关问题