reactjs - 如何使用mapbox在同一图层中绘制多个不同颜色的点?
问题描述
我想使用 mapbox 在同一图层中绘制多个点,所有这些点都将具有自己的属性,例如颜色和标签。并且在单击单个点时,它应该显示一个带有该点 ID 的弹出窗口。
这是否可以实现,到目前为止,我一直在循环点数组,并且为每个点创建一个单独的源和层。
for(let i = 0; i < buildings.length; i++){
let mapSource = map.getSource(buildings[i].building_id);
if(!mapSource){
map.addSource(buildings[i].building_id, {
'type': 'geojson',
'data': {
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': buildings[i].centroid.coordinates
}
}
});
}
let mapLayer = map.getLayer(buildings[i].building_id);
if(!mapLayer){
map.addLayer({
'id': buildings[i].building_id,
'type': 'circle',
"paint": {
"circle-radius": 6,
"circle-color": SectionColors[buildings[i].section[0]]
},
"source": buildings[i].building_id
});
}
let mapLabel = map.getLayer(`${buildings[i].building_id}-label`);
if(!mapLabel){
map.addLayer({
'id': `${buildings[i].building_id}-label`,
'type': 'symbol',
'source': buildings[i].building_id,
'layout': {
'text-field': `${buildings[i].building_id}`,
'text-size': 14,
'text-variable-anchor': ["left"],
'text-radial-offset': 0.3,
'text-justify': 'auto',
},
'paint': {
'text-color': '#fff308'
}
});
}
map.on('click', buildings[i].building_id, function(e){
setPopUpTop(e.point.y+10);
setPopUpLeft(e.point.x+10);
setBuildingPopup(true);
setBuilding(buildings[i].building_id);
setInfoPanel(false);
});
map.on('mousemove', buildings[i].building_id, function(e){
map.getCanvas().style.cursor = 'pointer';
if(buildings[i].section){
let sectionBuildings = buildings.filter(item => item.section && item.section.includes(buildings[i].section[0]))
for(let j = 0; j < sectionBuildings.length; j++){
let mapLayer = map.getLayer(`${sectionBuildings[j].building_id}-borders-onHover`);
if(typeof mapLayer === 'undefined'){
map.addLayer({
'id': `${sectionBuildings[j].building_id}-borders-onHover`,
'type': 'circle',
'source': sectionBuildings[j].building_id,
"paint": {
"circle-radius": 8,
"circle-color": '#fff308'
},
});
}
}
}
});
map.on('mouseleave', buildings[i].building_id, function(e){
map.getCanvas().style.cursor = '';
if(buildings[i].section){
let sectionBuildings = buildings.filter(item => item.section && item.section.includes(buildings[i].section[0]))
for(let j = 0; j < sectionBuildings.length; j++){
let mapLayer = map.getLayer(`${sectionBuildings[j].building_id}-borders-onHover`);
if(typeof mapLayer !== 'undefined'){
map.removeLayer(`${sectionBuildings[j].building_id}-borders-onHover`);
}
}
}
});
}
当点数很少时,性能差异不大,但是当我绘制大量点(如 300-400)时,性能非常慢。
解决方案
您需要做的第一件事是使用特征集合在一个源中包含多个点:
map.addSource('multiple-points-source', {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"color": "#FFFFFF"
},
"geometry": {
"type": "Point",
"coordinates": [-46.757, 71.413]
}
},
{
"type": "Feature",
"properties": {
"color": "#000000"
},
"geometry": {
"type": "Point",
"coordinates": [-32.345, 72.816]
}
}
]
}
之后,您可以使用数据驱动的样式来用点特征属性中的颜色填充圆圈:
map.addLayer({
'id': 'multiple-points-layer',
'type': 'circle',
'source': 'multiple-points-source',
'layout': {
},
'paint': {
// use data-driven styling
'circle-color': ['get', 'color'],
},
});
这是一个使用这种技术的工作示例:https ://jsfiddle.net/132ygokd/2/
推荐阅读
- django - 禁用多选 Django 小部件中的选择
- reactjs - 如何通过单击同级组件在反应中显示/隐藏组件
- javascript - 是否需要打开谷歌表才能运行功能?
- python - 通过 Okta 身份验证使用 Databricks Snowflake 连接器连接到 Snowflake
- javascript - 如何为客户端可视化的快速排序算法添加延迟间隔?
- meteor - Meteor 和 withTracker:为什么一个组件会渲染两次?
- spring-boot - Spring Boot Multi Module Gradle Project 类路径问题:Package Not Found, Symbol not Found
- arrays - 使用 Laravel 从数据库中返回嵌套的 Json 作为数组
- javascript - TypeError: undefined is not a function ('...data.map...' 附近)
- networking - route print 命令显示几乎所有 On-link 网关