Mapbox GL JS刷新层

时间:2018-04-22 16:07:01

标签: javascript mapbox mapbox-gl-js

我正在使用Chroma.js来设置Mapbox等值区域的样式。我通过在变量dataStyleProp中存储源的单个属性来做到这一点 - 在这种情况下,数据是填充,属性是“free”,“slave”,“white”和“total”。然后我使用dataStyleProp来构建Chroma.js色标。我想做的是:

  1. 从HTML页面上的单选按钮
  2. 中选择dataStyleProp的值
  3. 将该值传递给Chroma脚本,
  4. 然后刷新地图以显示新的等值线。
  5. 我设法做了1.和2.但是不能让3.工作。我已尝试map.updatemap.resize尝试强制刷新,但都不起作用。我还查看了map.getSource(source).setData(data),但传递的数据必须是geojson,我的dataStyleProp是一个字符串。

    我考虑为每个dataStyleProp值创建一个新图层,但这意味着要创建数百个额外图层(每个图源至少有4个不同的dataStyleProp值),我想避免创建如果可能,所有这些额外的层。

    如何刷新地图以显示新的dataStyleProp色标?

    HTML:

    <div id="map"></div>
    <div>
      <ul class="sidebar-list">
        <li id="dataInput"> 
          <div id="data1"></div>
          <div id="data2"></div>
          <div id="data3"></div>
          <div id="data4"></div>
          <div><button id="update">Update</button></div>
        </li>
      </ul>
    </div>
    

    JS:

    mapboxgl.accessToken = "myaccesstoken";
    var map = new mapboxgl.Map({
        container: "map",
        style: "mapbox://styles/mystyle",  
        center: [-100.04, 38.907],
        minZoom: 3
        });
    
    function loadAll() {
      function getStates() {
        return fetch("data/1790_state_race.json").then(function(response) {
            return response.json();
            });
        }
    
      getStates().then(function(response) {
        states1790race = response;
        console.log(states1790race);
        });
    
    all = $.when(states1790race); 
    
    all.done(function() {  
    
        var vtMatchProp = "GISJOIN";
        var dataMatchProp = "GISJOIN";
    
        map.on("load", function () {
          map.addSource("states1790", {
                type: "vector",
                url: "mapbox://statessource"  
                });
    
          map.addSource("1790", {
                "type": "vector",
                "url": "mapbox://countiessource"
                });
    
          if (document.getElementsByName("dataInput").value === undefined) {
            var dataStyleProp = "TOTAL";
            }  
        var dataInput = document.getElementsByName("dataInput");
                $("#update").on("click", function() {
                        for (var i = 0; i < dataInput.length; i++) {
                                if (dataInput[i].checked) {
                                    dataStyleProp = dataInput[i].value;
                                    break;
                                    }
                                }
                        console.log(dataStyleProp);
    
                        //refresh map layer here???
    
                        });
    
        var stops = [["0", "rgba(227,227,227,0)"]];
        var numbers1790 = states1790race.map(function(val) {
                return Number(val[dataStyleProp])
                });
        //chroma quantile scale
        var limits1790 = chroma.limits(numbers1790, 'q', 9);
    
        //chroma color scale
        var colorScale = chroma.scale(["#ffe8c6", "#915c0e"]).mode("lch").colors(10);
    
        var newData1790 = states1790race.map(function(state) {
            var color = "#e3e3e3";
            for (var i = 0; i < limits1790.length; i++) {
                if (state[dataStyleProp] <= limits1790[i]) {
                  color = colorScale[i];
                  break;
                  }
                }
            var id = state[dataMatchProp];
            return [id, color]
        });
    
    map.addLayer({
            "id": "1790states",
            "source": "states1790",
            "source-layer": "USA-states-1790",
            "type": "fill",
            "layout": { "visibility": "visible" }, 
                "paint": {
                    "fill-color": {
                        "property": vtMatchProp,
                        "type": "categorical",
                        "stops": newData1790
                        }, 
                    "fill-outline-color": "white",
                    "fill-opacity": 1
                    } 
                });  
    
    });
    
    map.on("click", function(e) {
    
            var features = map.queryRenderedFeatures(e.point, { layers: ["1790states", "1790counties" ] });
            map.getCanvas().style.cursor = (features.length) ? "pointer": "";
    
            var feature = features[0];
    
    
            if (feature.properties.COUNTY == undefined) {
                for (var i = 0; i < states1790race.length; i++) {
                    if (feature.properties.GISJOIN == states1790race[i].GISJOIN) {
                        total = states1790race[i].TOTAL;
                        free = states1790race[i].FREE;
                        slave = states1790race[i].SLAVE;
                        white = states1790race[i].WHITE;
                        year = states1790race[i].YEAR;
                        document.getElementById("data1").innerHTML = "<input type='radio' checked name='dataInput' value='TOTAL'> Total State Population: " + addCommas(total);
                        document.getElementById("place").innerHTML = feature.properties.STATENAM;
                        }
                    } 
    
                } else if 
    
                 (feature.properties.COUNTY != undefined) {
                for (var j = 0; j < counties1790race.length; j++) {
                    if (feature.properties.GISJOIN == counties1790race[j].GISJOIN) {
                        total = counties1790race[j].TOTAL;
                        free = counties1790race[j].FREE;
                        slave = counties1790race[j].SLAVE;
                        white = counties1790race[j].WHITE;
                        year = counties1790race[j].YEAR;
                        document.getElementById("data1").innerHTML = "<input type='radio' checked name='dataInput' value='TOTAL'> Total County Population: " + addCommas(total);
                        document.getElementById("place").innerHTML = feature.properties.NHGISNAM + " County, " + feature.properties.STATENAM;
                        }
                    } 
                }
    
            if (feature.properties.STATENAM != undefined) {
                var buildings = map.querySourceFeatures(e.point);
                document.getElementById("data2").innerHTML = "<input type='radio' name='dataInput' value='FREE'> Free: " + addCommas(free);
                document.getElementById("data3").innerHTML = "<input type='radio' name='dataInput' value='SLAVE'> Slave: " + addCommas(slave);
                document.getElementById("data4").innerHTML = "<input type='radio' name='dataInput' value='WHITE'> White: " + addCommas(white);
                document.getElementById("timeline").innerHTML = "Population in " + year;
                }
    
        });
    
      });
    
    }
    

1 个答案:

答案 0 :(得分:1)

我对你要做的事情感到有点困惑(我不知道Chroma是什么),但看起来你正试图以某种方式动态更新Mapbox上托管的矢量图块源的属性。你不能这样做。

您基本上有两个动态数据可视化选项:

  1. 在浏览器中生成GeoJSON,并调用map.setData()进行显示。
  2. 保持地图数据静态,但生成一个巨大的数据驱动属性以使其可视化:“如果状态名称= X,则将其绘制为淡粉色。如果状态名称= Y,则将其绘制为淡蓝色”等。
  3. 如果您已经拥有了瓷砖组中的所有数据和所有地理位置,那么我不清楚您的问题是什么,或者为什么您无法“刷新”它。只需致电setPaintProperty甚至setStyle即可更新可视化效果。