javascript - Mapbox GL JS 刷新图层

标签 javascript mapbox mapbox-gl-js

我正在使用 Chroma.js 来设计 Mapbox 等值线图的样式。我通过在变量 dataStyleProp 中存储源的单个属性来做到这一点——在这种情况下,数据是人口,属性是“自由”、“奴隶”、“白色”和“总计” ”)。然后我使用 dataStyleProp 构建 Chroma.js 色标。我想做的是:

  1. 从 HTML 页面上的单选按钮中选择 dataStyleProp 的值,
  2. 将该值传递给 Chroma 脚本,
  3. 然后刷新 map 以显示新的等值线。

我已经设法完成了 1. 和 2. 但无法让 3. 工作。我尝试了 map.updatemap.resize 来尝试强制刷新,但都不起作用。我还查看了 map.getSource(source).setData(data) 但传递的数据必须是 geojson 而我的 dataStyleProp 是一个字符串。

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

如何刷新 map 以显示新的 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;
            }

    });

  });

}

最佳答案

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

动态数据可视化基本上有两种选择:

  1. 在浏览器中生成一个 GeoJSON,并调用 map.setData() 显示它。
  2. 保持 map 数据静态,但生成一个巨大的数据驱动属性以将其可视化:“如果州名称 = X,将其绘制为淡粉色。如果州名称 = Y,将其绘制为淡蓝色”等。

如果您已经在 tileset 中拥有所有数据和所有地理位置,那么我不清楚您的问题是什么,或者为什么您无法“刷新”它。只需调用 setPaintProperty 甚至 setStyle 即可更新可视化效果。

关于javascript - Mapbox GL JS 刷新图层,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49967994/

相关文章:

javascript - 将 cURL HTML 数据提供给 AngularJs

javascript - 通知 - 替代 Object.observe?

javascript - 返回键不适用于许多文本区域

javascript - Mapbox JS SDK 地理编码客户端未定义

javascript - 尽管图层缩放设置等于 [0, 22],Mapbox 样式图层有时会隐藏

javascript - 如何抑制发生的所有 JavaScript 错误,包括控制台中的错误?

android - 自定义 Mapbox fragment 信息布局

javascript - 从 URL 将 GeoJSON 加载到图层中?

javascript - Mapbox GL JS : Fullscreen and GPS button Issues in Chrome only

react-native - 一旦 cocoapods 从 Podfile 安装 react-native-mapbox-gl,Xcode 就会成功构建损坏的存档,而不显示在组织器中