我正在使用Chroma.js来设置Mapbox区域地图的样式。我通过将变量的单个属性存储在变量dataStyleProp
中来实现此目的-在这种情况下,数据为填充,属性为“自由”,“从属”,“白色”和“总计”)。然后,我使用dataStyleProp
构建Chroma.js色标。我想做的是:
从HTML页面上的单选按钮中选择dataStyleProp
的值,
将该值传递给Chroma脚本,
然后刷新地图以显示新的合奏。
我已经设法做过1.和2.,但是无法使3.正常工作。我已经尝试过map.update
和map.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;
}
});
});
}
最佳答案
对于您要执行的操作,我有些困惑(我不知道Chroma是什么),但似乎您正在尝试以某种方式动态更新Mapbox上托管的矢量图块源的属性。你做不到
对于动态数据可视化,基本上有两种选择:
在浏览器中生成GeoJSON,然后调用map.setData()
进行显示。
保持地图数据静态,但生成一个巨大的数据驱动属性以使其可视化:“如果状态名称= X,则将其绘制为浅粉色。如果状态名称= Y,则将其绘制为浅蓝色”等。
如果您已经在磁贴集中拥有所有数据和所有地理位置,那么我不清楚您的问题是什么,或者为什么您无法“刷新”该问题。只需调用setPaintProperty
甚至setStyle
即可更新可视化效果。