Leaflet地图中ApexCharts仪表盘覆盖信息面板内容如何解决?
问题修复方案
根因说明
- ApexCharts的
render()方法为异步执行:你当前的代码先触发图表渲染,再同步更新信息面板文本,等图表异步渲染完成后,会直接清空你挂载的整个.info根容器的原有内容,导致先出现的文本被后续渲染的图表覆盖 - 未对信息面板做功能分区,文本和图表共用同一个根容器,渲染逻辑互相冲突
修复步骤
1. 拆分信息面板容器结构
修改createInfoPanel方法,提前在信息面板根容器内创建两个独立子容器,分别存放文本信息和图表,避免后续渲染互相覆盖。
2. 调整更新逻辑
信息面板的update方法仅修改文本子容器的内容,不再覆盖整个根容器的HTML。
3. 修正图表挂载节点
将ApexCharts的挂载节点改为专门的图表子容器,不再直接挂载到信息面板根容器。
4. 优化图表实例管理
新增全局变量存储图表实例,每次渲染新图表前销毁旧实例,避免内存泄漏和重复渲染。
完整修改后代码
// 新增全局变量存储图表实例,方便销毁 let waterSystemChart = null; function createInfoPanel(){ info_panel.onAdd = function (map) { // 创建根容器 this._div = L.DomUtil.create('div', 'info'); // 新增两个独立子容器:文本区、图表区 this._div.innerHTML = ` <div class="info-content"></div> <div class="info-chart" style="margin-top: 15px;"></div> `; this.update(); return this._div; }; info_panel.update = function (properties) { // 仅更新文本容器内容,不触碰整个根容器和图表容器 const contentEl = this._div.querySelector('.info-content'); if(properties){ contentEl.innerHTML = `<b>${properties['name']}</b> <br>Governance Type: ${properties['GovernanceType']} <br>Next Election Year: ${properties['UpcomingElectionYear']} <br>How is Leadership Chosen?: ${properties['Mechansim']} <br>Average Water Bill: $${properties['WaterBill']} <br>Bill Compared to County Average: ${properties['POA']} `; }else{ contentEl.innerHTML = 'Hover over a Water System'; // 鼠标移出时清空图表 const chartEl = this._div.querySelector('.info-chart'); chartEl.innerHTML = ''; if(waterSystemChart){ waterSystemChart.destroy(); waterSystemChart = null; } } }; info_panel.addTo(map); } // Function that defines what will happen on user interactions with each feature function onEachFeature(feature, layer) { layer.on({ mouseover: highlightFeature, mouseout: resetHighlight, click: zoomToFeature }); } // on mouse over, highlight the feature function highlightFeature(e) { var layer = e.target; // style to use on mouse over layer.setStyle({ weight: 2, color: '#666', fillOpacity: 0.7 }); if (!L.Browser.ie && !L.Browser.opera && !L.Browser.edge) { layer.bringToFront(); } // 先更新文本信息,再渲染图表 info_panel.update(layer.feature.properties); createDashboard(layer.feature.properties); } // on mouse out, reset the style, otherwise, it will remain highlighted function resetHighlight(e) { geojson_layer.resetStyle(e.target); info_panel.update() // resets infopanel } // on mouse click on a feature, zoom in to it function zoomToFeature(e) { map.fitBounds(e.target.getBounds()); } // Creating dashboard function createDashboard(properties){ // 先销毁旧图表 if(waterSystemChart){ waterSystemChart.destroy(); waterSystemChart = null; } console.log(properties) // data values let data = [ properties['Hispanic_Pop'], properties['White_Pop'], properties['Black_Pop'], properties['AIAN_Pop'], properties['Asian_Pop'], properties['NHOPI_Pop'], properties['OtherRace_Pop'], properties['TwoMore_Pop'], ] // data fields let fields = [ 'Hispanic Population', 'White Population', 'Black Population', 'American Indian and Alaskan Native Population ', 'Asian Population', 'Native Hawaiian and other Pacific Islander Population', 'Other Race Population', 'Two or more Race Population', ] var options2 = { chart: { type: 'pie', height: 300, width: '100%', animations: { enabled: false, } }, title: { text: 'Water System Demographics ' + properties['name'], }, series: data, labels: fields, legend: { position: 'right', offsetY: 0, height: 230, } }; // 挂载到专门的图表子容器,不再挂载到整个.info容器 waterSystemChart = new ApexCharts(document.querySelector('.info .info-chart'), options2) waterSystemChart.render() }
可选优化
可以给.info容器加固定宽度、最大高度和滚动样式,避免内容过长影响地图操作:
.info { padding: 10px; background: white; border-radius: 5px; box-shadow: 0 0 10px rgba(0,0,0,0.2); min-width: 300px; max-height: 80vh; overflow-y: auto; }
内容的提问来源于stack exchange,提问作者prock
相关产品推荐
相关产品推荐

