Requests exceeding maximum URL length in Fusion Tables layer

主宰稳场 提交于 2019-12-02 07:22:53
approxiblue

If you use the Fusion Tables layer, your map tile requests will end up with long query strings exceeding the maximum URL length. There are no layer settings to use POST instead of GET requests, so we'll have to avoid the problem by filtering map results client-side.

Inspired by this answer, we can:

  1. Use the Fusion Tables API, request all map data at once. The results will be huge, but the GET request is small:

    https://www.googleapis.com/fusiontables/v2/query?sql=select GEO_ID2, geometry from 1xdysxZ94uUFIit9eXmnw1fYc6VcQiXhceFd_CVKa&key=<YOUR_API_KEY>
    
  2. Wrangle data. The "geometry" column is in GeoJSON. There are a few issues with the returned format: the outermost wrapping object is inconsistent, and the coordinate lists of the polygons don't have the same start and end points.

  3. Draw the GeoJSON features on the map using the Data layer. Adding styles and interactivity for the features is well-documented.

For this demo, only a small set of IDs is used, and IDs are looked up using array's indexOf(). With more IDs, consider using a faster lookup table.

html,
body,
#map {
  height: 100%;
  margin: 0;
  padding: 0;
}
<div id="map"></div>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?v=3"></script>
<script>
  var ids = ['17015', '17043', '17053', '17077', '17079', '17081', '17129', '17141', '17197', '18019', '18043', '18067'];

  var map;

  function initialize() {
    var mapOptions = {
      zoom: 7,
      disableDefaultUI: true,
      center: {
        lat: 41.8781,
        lng: -87.6298
      }
    };

    map = new google.maps.Map(document.getElementById('map'), mapOptions);
    map.data.setStyle({
      strokeWeight: 0,
      fillOpacity: 0.3,
    });

    // Basic interactivity
    map.data.addListener('mouseover', function(event) {
      map.data.revertStyle();
      map.data.overrideStyle(event.feature, {
        fillColor: '#FF0000',
        fillOpacity: 0.5,
      });
    });

    map.data.addListener('mouseout', function(event) {
      map.data.revertStyle();
    });

    // Send Fusion Tables JSONP request
    var url = ['https://www.googleapis.com/fusiontables/v2/query'];
    url.push('?sql=' + encodeURIComponent('SELECT GEO_ID2, geometry FROM 1xdysxZ94uUFIit9eXmnw1fYc6VcQiXhceFd_CVKa'));
    url.push('&callback=drawMap');
    url.push('&key=AIzaSyBMtoh9P3UkoxbXndKu_HOP7KsVwTRvxGU');
    var script = document.createElement('script');
    script.src = url.join('');
    document.getElementsByTagName('body')[0].appendChild(script);
  }

  function drawMap(data) {
    var rows = data['rows'];

    for (var i = 0, rc = rows.length; i < rc; i++) {
      if (ids.indexOf(rows[i][0]) !== -1) {
        var geojson = {
          type: 'Feature',
          properties: {
            name: rows[i][0], // GEO_ID2
          }
        }

        // Second column: geometry (GeoJSON)
        var geometries = rows[i][1]['geometries'];
        if (geometries) {
          geojson['geometry'] = rows[i][1];
          for (var g = 0, len = geometries.length; g < len; g++) {
            validateLinearRings(geometries[g]['coordinates']);
          }
        } else {
          geojson['geometry'] = rows[i][1]['geometry'];
          validateLinearRings(geojson['geometry']['coordinates']);
        }

        map.data.addGeoJson(geojson);
      }
    }
  }

  function validateLinearRings(coordinates) {
    var len = coordinates.length;
    for (var i = 0; i < len; i++) {
      // Add the first point as the last, closing the loop
      // http://geojson.org/geojson-spec.html#linestring
      coordinates[i].push(coordinates[i][0]);
    }
  }

  google.maps.event.addDomListener(window, 'load', initialize);
</script>

The problem is the length of the request URL. Errors in the javascript console:

Failed to load resource: the server responded with a status of 400 ()
https://maps.googleapis.com/maps/vt?pb=!1m4!1m3!1i5!2i6!3i11!1m4!1m3!1i5!2i…Q!5i1!3m3!2sen-US!3sUS!5e18!4e3!12m1!5b1&callback=_xdc_._1mbvg&token=38465 

You need to reduce the length of the query string. One option (for this specific case, probably doesn't scale to all possible issues) is to remove the leading 0's in the query:

var draw_str = ['6037', '6043', '6057', '6065', '6079', '6097', '8011', '8037', '8051', '8069', '8099', '8119', '12041', '12075', '12113', '12123', '13015', '13029', '13095', '13151', '13161', '13169', '13197', '13209', '13213', '13235', '13263', '13267', '13273', '13275', '13293', '13305', '13319', '13990', '16017', '16023', '16047', '16049', '17015', '17043', '17053', '17077', '17079', '17081', '17129', '17141', '17197', '18019', '18043', '18067', '18105', '18115', '18119', '18127', '18147', '19013', '19031', '19067', '19079', '19087', '19111', '19113', '19127', '19153', '19161', '19169', '19175', '19187', '20009', '20019', '20037', '20039', '20051', '20059', '20067', '20087', '1017', '1035', '1053', '1073', '1081', '1127', '2282', '5007', '5031', '5039', '5053', '5067', '5087', '5089', '5119', '5123', '37025', '37037', '37057', '37077', '37123', '37153', '37157', '37159', '37193', '38017', '38045', '38051', '38065', '38101', '39007', '39019', '39021', '39049', '39057', '39059', '39063', '39069', '39081', '39089', '39091', '39097', '39101', '39139', '39153', '39167', '40003', '40019', '40087', '40129', '40153', '41011', '41027', '41049', '42013', '42021', '42035', '42037', '42041', '42055', '42063', '42073', '42077', '42085', '42091', '42109', '42115', '42131', '72027', '72051', '72055', '72057', '72065', '72073', '72087', '72129', '45033', '45035', '45059', '45071', '20095', '20099', '20101', '20107', '20109', '20117', '20133', '20139', '20177', '20195', '20209', '21029', '21031', '21037', '21059', '21061', '21083', '21113', '21127', '21157', '21173', '21211', '21217', '21229', '21239', '22013', '22035', '22049', '22055', '22065', '22079', '22103', '23005',  '23025'];

proof of concept fiddle

code snippet:

html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}
#map {
  height: 100%;
  zoom: 0.7;
  -moz-transform: scale(0.8);
  -moz-transform-origin: 0 0;
}
<div id="map"></div>
<script>
  var arr = ['37159'];
  var draw_str = ['6037', '6043', '6057', '6065', '6079', '6097', '8011', '8037', '8051', '8069', '8099', '8119', '12041', '12075', '12113', '12123', '13015', '13029', '13095', '13151', '13161', '13169', '13197', '13209', '13213', '13235', '13263', '13267', '13273', '13275', '13293', '13305', '13319', '13990', '16017', '16023', '16047', '16049', '17015', '17043', '17053', '17077', '17079', '17081', '17129', '17141', '17197', '18019', '18043', '18067', '18105', '18115', '18119', '18127', '18147', '19013', '19031', '19067', '19079', '19087', '19111', '19113', '19127', '19153', '19161', '19169', '19175', '19187', '20009', '20019', '20037', '20039', '20051', '20059', '20067', '20087', '1017', '1035', '1053', '1073', '1081', '1127', '2282', '5007', '5031', '5039', '5053', '5067', '5087', '5089', '5119', '5123', '37025', '37037', '37057', '37077', '37123', '37153', '37157', '37159', '37193', '38017', '38045', '38051', '38065', '38101', '39007', '39019', '39021', '39049', '39057', '39059', '39063', '39069', '39081', '39089', '39091', '39097', '39101', '39139', '39153', '39167', '40003', '40019', '40087', '40129', '40153', '41011', '41027', '41049', '42013', '42021', '42035', '42037', '42041', '42055', '42063', '42073', '42077', '42085', '42091', '42109', '42115', '42131', '72027', '72051', '72055', '72057', '72065', '72073', '72087', '72129', '45033', '45035', '45059', '45071', '20095', '20099', '20101', '20107', '20109', '20117', '20133', '20139', '20177', '20195', '20209', '21029', '21031', '21037', '21059', '21061', '21083', '21113', '21127', '21157', '21173', '21211', '21217', '21229', '21239', '22013', '22035', '22049', '22055', '22065', '22079', '22103', '23005', '23025'];

  function initMap() {
    var map = new google.maps.Map(document.getElementById('map'), {
      zoom: 5,
      disableDefaultUI: true,
      center: {
        lat: 38.755724,
        lng: -96.492369
      }
    });
    mark();
    //Draw layer Function
    function mark() {
      layer = new google.maps.FusionTablesLayer({
        query: {
          select: 'geometry',
          from: '1xdysxZ94uUFIit9eXmnw1fYc6VcQiXhceFd_CVKa'
        },
        styles: [{
          polygonOptions: {
            fillColor: '#000000',
            fillOpacity: 0.001
          }
        }, {
          //
          where: "'GEO_ID2' IN (" + draw_str.toString() + ")",

          polygonOptions: {
            fillOpacity: 0.3
          }
        }]
      });
      layer.setMap(map);
    }
  }
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap">
</script>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!