Google地图API v3:数据层ID未定义 [英] Google Maps API v3: data layer IDs undefined

查看:161
本文介绍了Google地图API v3:数据层ID未定义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我正在构建一个使用从MYSQL数据库中解析的数据的地图通过PHP设置由geoJson文件定义的多边形的颜色(它使用这个例如在谷歌开发网站作为模板)。我遇到的问题是数据层不会在页面加载时自动初始化。



完整的javascript / HTML在下面发布,但代码部分我在下面初始化数据层的例子中使用的是:

  google.maps.event.addListenerOnce(map .data,'addfeature',function(){
google.maps.event.trigger(document.getElementById('price_select'),
'change');
});

这给我错误Uncaught TypeError:无法读取未定义属性'setProperty'。如果我注释掉侦听器,数据层将会正常加载,但只能在下拉菜单中手动选择一个新输入(id ='price_select')。

<我加载的geoJson文件相对较大(约14mb),所以我认为发生的事情是在整个文件加载之前监听器正在触发('addfeature'等待第一个要添加的功能,但是我> 2000),因此由PHP解析的区域还没有相应的要素ID,该ID由loadGeoJson中的 idPropertyName:'Name'参数设置呼叫。我不知道一种方法来设置侦听器只触发一次整个GeoJson文件加载。或者,我可能完全错误,因为这是错误的原因。



无论如何,下面的完整代码 - 我知道它有一些怪癖(例如,我通过loadData函数一个参数,但不要使用它),但这些主要是因为我打算稍后添加更多功能。感谢您的支持!

 < script src =https://maps.googleapis.com/maps/api/ ?JS v = 3.exp>< /脚本> 
< script>

var map;

var priceMin = 1000000;
var priceMax = 0;

google.maps.event.addDomListener(window,'load',function(){

map = new google.maps.Map(document.getElementById('map- ),{b $ b center:new google.maps.LatLng(53.587425,-1.663539),
zoom:7,
});

// add样式
map.data.setStyle(styleFeature);
map.data.addListener('mouseover',mouseInToRegion);
map.data.addListener('mouseout',mouseOutOfRegion);


//启动下拉功能
var selectBox = document.getElementById('price_select');
google.maps.event.addDomListener(selectBox,'change',函数(){
clearData();
loadData(selectBox.options [selectBox.selectedIndex] .value);
});


/ / load polygons
loadMapShapes();

});

函数loadMapShapes(){

map.data.loadGeoJson('http://localhost/OS_raw.json',
{idPropertyName:'Name'} );

//这是应该启动数据层的监听器

google.maps.event.addListenerOnce(map.data,'addfeature',function(){
google.maps.event.trigger(document.getElementById('price_select'),
'change');
});

//结束监听器


}

函数loadData(变量){

var phpdistricts = (<?php echo $ phpdistricts;?>);
var phpprices =(<?php echo $ phpprices;?>);



(var i = 0; i< phpdistricts.length; i ++){

var district = phpdistricts [i];
var price = parseInt(phpprices [i]);

//记录最小值和最大值
if(price priceMin = price;
}
if(price> priceMax){
priceMax = price;
}


console.log(map.data.getFeatureById(district));

//这是错误触发的位置 - 功能根据控制台日志未定义
map.data
.getFeatureById(区)
.setProperty('price ',price);}

//有问题的部分结束

//更新并显示图例
document.getElementById('census-min')。 textContent =
priceMin.toLocaleString();
document.getElementById('census-max')。textContent =
priceMax.toLocaleString();

}

函数clearData(){
priceMin = 1000000;
priceMax = 0;
map.data.forEach(function(row){
row.setProperty('price',undefined);
});
document.getElementById('data-box')。style.display ='none';
document.getElementById('data-caret')。style.display ='none';
}

函数styleFeature(feature){
var low = [151,83,34]; //最小数据的颜色
var high = [5,69,54]; //最大基准的颜色

// delta表示值位于最小值和最大值之间的位置
var delta =(feature.getProperty('price') - priceMin)/
(priceMax - priceMin);

var color = [];
for(var i = 0; i <3; i ++){
//基于delta
color [i] =(high [i] - low [ i])* delta + low [i];
}

//过滤掉没有数据的区域
var showRow = true;
if(feature.getProperty('price')== null ||
isNaN(feature.getProperty('price'))){
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
};


函数mouseInToRegion(e){
//设置悬停状态,所以setStyle函数可以改变边界
e.feature.setProperty('state' ,'hover');

var percent =(e.feature.getProperty('price') - priceMin)/
(priceMax - priceMin)* 100;

//更新标签
document.getElementById('data-label')。textContent =
e.feature.getProperty('Name');
document.getElementById('data-value')。textContent =
e.feature.getProperty('price');
document.getElementById('data-box')。style.display ='block';
document.getElementById('data-caret')。style.display ='block';
document.getElementById('data-caret')。style.paddingLeft = percent +'%';


函数mouseOutOfRegion(e){
//重置悬停状态,将边框返回正常
e.feature.setProperty('state','正常');
}


< / script>
< / head>
< body>
< div id =controlsclass =nicebox>
< div>
< select id =price_select>
< option value =price> 2014年6月< / option>
< option value =price> 2014年6月< / option>
< / select>
< / div>

< div id =legend>
< div id =census-min> min< / div>
< div class =color-key>
< span id =data-caret>◆< / span>
< / div>
< div id =census-max> max< / div>
< / div>
< / div>
< div id =data-boxclass =nicebox>
< label id =data-labelfor =data-value>区域:< / label>
< span id =data-value>< / span>
< / div>
< div id =map-canvas>< / div>
< / body>
< / html>


解决方案

在这里,但你有没有尝试使用数据层事件,而不是地图的样式?

  map.data.setStyle(
函数(特征){
//根据特征属性在这里构建您的样式

return style_i_want_for_this_feature;
}
);

这将在您的GeoJSON数据中为每个要素调用,并且可以适当地对待它。我通过这种方式加载和设置了数千个功能。

long-time lurker, first-time poster here, so be gentle...

I'm building a map that uses data parsed in from a MYSQL db via PHP to set the colour of polygons defined by a geoJson file (it uses this example on the Google dev site as a template). The problem I'm having is that the data layer won't automatically initialize when the page loads.

The full javascript/HTML is posted below, but the section of code that was used in the example I'm following to initialize the data layer is:

  google.maps.event.addListenerOnce(map.data, 'addfeature', function() {
  google.maps.event.trigger(document.getElementById('price_select'),
        'change');
  });

This gives me the error "Uncaught TypeError: Cannot read property 'setProperty' of undefined". If I comment out the listener, the data layer will load fine, but only after I've manually selected a new input from the drop down (id='price_select').

The geoJson file I'm loading is relatively large (~14mb) so I think what is happening is that the listener is triggering before the whole file is loaded ('addfeature' waits for just the first feature to be added, but I have >2000) and thus the districts parsed in by the PHP don't yet have a corresponding feature ID, which is set by the idPropertyName: 'Name' parameter in the loadGeoJson call. I don't know of a way to set the listener to trigger only once the whole GeoJson file has loaded though. Alternatively, I could be completely wrong about this being the cause of the error.

Anyway, full code below - I know it has some quirks (e.g. I pass the loadData function an argument, but don't use it), but these are mainly because I plan to add more functionality later on. Thanks for bearing with me!

    <script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
        <script>

        var map;

        var priceMin = 1000000;
        var priceMax = 0;

        google.maps.event.addDomListener(window, 'load', function(){

            map = new google.maps.Map(document.getElementById('map-canvas'), {
            center: new google.maps.LatLng(53.587425,-1.663539),
             zoom: 7,
            }); 

        // add styles
        map.data.setStyle(styleFeature);
        map.data.addListener('mouseover', mouseInToRegion);
        map.data.addListener('mouseout', mouseOutOfRegion);


      // initiate drop down functionality
      var selectBox = document.getElementById('price_select');
      google.maps.event.addDomListener(selectBox, 'change', function() {
        clearData();
        loadData(selectBox.options[selectBox.selectedIndex].value);
      });


      // load polygons
      loadMapShapes();

    });     

    function loadMapShapes(){

     map.data.loadGeoJson('http://localhost/OS_raw.json',
        { idPropertyName: 'Name' }); 

  //This is the listener that is supposed to initiate the data layer

      google.maps.event.addListenerOnce(map.data, 'addfeature', function() {
      google.maps.event.trigger(document.getElementById('price_select'),
            'change');
      });

 // End listener   


    }

    function loadData(variable){

        var phpdistricts = (<?php echo $phpdistricts; ?>);
        var phpprices = (<?php echo $phpprices; ?>);



        for(var i=0; i<phpdistricts.length; i++){

            var district = phpdistricts[i];
            var price = parseInt(phpprices[i]);

            // keep track of min and max values
            if (price < priceMin) {
            priceMin = price;
            }
            if (price > priceMax) {
            priceMax = price;
            }


            console.log(map.data.getFeatureById(district));

   //This is where the error triggers - feature is undefined according to console log above
            map.data
            .getFeatureById(district)
            .setProperty('price', price);}

   //end of problematic section        

            // update and display the legend
            document.getElementById('census-min').textContent =
                priceMin.toLocaleString();
            document.getElementById('census-max').textContent =
                priceMax.toLocaleString();    

    }

    function clearData() {
      priceMin = 1000000;
      priceMax = 0;
      map.data.forEach(function(row) {
        row.setProperty('price', undefined);
      });
      document.getElementById('data-box').style.display = 'none';
      document.getElementById('data-caret').style.display = 'none';
    }

    function styleFeature(feature) {
      var low =  [151, 83, 34]; // color of smallest datum
      var high = [5, 69, 54];   // color of largest datum

      // delta represents where the value sits between the min and max
      var delta = (feature.getProperty('price') - priceMin) /
          (priceMax - priceMin);

      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];
      }

      // filters out areas without data
      var showRow = true;
      if (feature.getProperty('price') == null ||
          isNaN(feature.getProperty('price'))) {
        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
      };
    }

    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('price') - priceMin) /
          (priceMax - priceMin) * 100;

      // update the label
      document.getElementById('data-label').textContent =
          e.feature.getProperty('Name');
      document.getElementById('data-value').textContent =
          e.feature.getProperty('price');
      document.getElementById('data-box').style.display = 'block';
      document.getElementById('data-caret').style.display = 'block';
      document.getElementById('data-caret').style.paddingLeft = percent + '%';
    }

    function mouseOutOfRegion(e) {
      // reset the hover state, returning the border to normal
      e.feature.setProperty('state', 'normal');
    }


        </script>
      </head>
      <body>
        <div id="controls" class="nicebox">
            <div>
            <select id="price_select">
                <option value="price">Jun '14</option>
                <option value="price">Jun '14</option>
            </select>
            </div>

            <div id="legend">
            <div id="census-min">min</div>
            <div class="color-key">
                <span id="data-caret">◆</span>              
            </div>
            <div id="census-max">max</div>          
            </div>
            </div>
        <div id="data-box" class="nicebox">
            <label id="data-label" for="data-value">Area: </label>
            <span id="data-value"></span>
        </div>
        <div id="map-canvas"></div>
      </body>
    </html>   

解决方案

I don't fully get what you're asking here, but have you tried styling using the data layer events, rather than the maps?

map.data.setStyle(
 function(feature){
   // Build your styles here based on feature properties.

    return style_i_want_for_this_feature;
 }
);

That will get called for each feature in your GeoJSON data, and you can treat it appropriately. I load and style feature collections with thousands of features this way.

这篇关于Google地图API v3:数据层ID未定义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆