如何在Leaflet弹窗中集成Chart.js并从popup元素读取数据生成图表?
实现方案
这个需求完全可以实现,核心逻辑为每次点击标记渲染完侧边弹窗内容后,直接从DOM中对应的评分类元素提取数值,更新已有的Chart.js实例即可,全程不需要读取原始GeoJSON数据,完全符合你适配后续JSON结构变动的要求。
核心修改步骤
1. 调整JS逻辑
首先全局保存图表实例,新增从弹窗提取数据更新图表的函数,再在标记点击事件中触发更新即可,修改后的完整JS代码如下:
var mymap = L.map('mapid').setView([39.46975, -0.37739], 8 ); L.tileLayer('https://api.mapbox.com/styles/v1/jamaldols/cktwljkom0vzo18l9ggtnky83/tiles/256/{z}/{x}/{y}@2x?access_token={accessToken}', { attribution: 'Map data © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>', maxZoom: 12, minZoom: 8, id: 'mapbox/standard', tileSize: 512, zoomOffset: -1, accessToken: '' }).addTo(mymap); // 全局保存雷达图实例 let radarChart; $.getJSON('data.geo.json', function (geojson) { L.geoJson(geojson, { pointToLayer: function (feature, latlng) { return L.marker(latlng); }, onEachFeature: function (feature, layer) { const coordinates = feature.geometry.coordinates; const normalizedCoordinates = feature.geometry.coordinates.sort(function(a,b){return a.typeid-b.typeid}); console.log( `Coordinates: ${coordinates}`); console.log( `Coordinates N: ${normalizedCoordinates}`); const content = ` <p id="heading">${feature.properties.name}</p> <p class="scoreA"><strong>ScoreA: </strong>${feature.properties.scoreA}</p> <p class="scoreB"><strong>ScoreB: </strong>${feature.properties.scoreB}</p> <p class="scoreC"><strong>ScoreC: </strong>${feature.properties.scoreC}</p> <p class="scoreD"><strong>ScoreD: </strong>${feature.properties.scoreD}</p> <div class="popup__chart">chart</div> `; layer.on('click', function (e) { document.getElementById("popup__content").innerHTML = content; // 渲染完弹窗内容后直接调用更新图表方法 updateChartFromPopup(); $(".popup").fadeOut(10); $(".popup").fadeIn("slow"); console.log( `Click on ${feature.properties.name}`); const maxZoom = mymap.getMaxZoom(); console.log(maxZoom) mymap.flyTo(this.getLatLng(), maxZoom, {easeLinearity: 0.12, duration:1}); }); } }).addTo(mymap); }); // 从弹窗DOM提取数据更新雷达图 function updateChartFromPopup() { // 提取各评分数值,自动过滤文本只保留数字 const scoreA = parseInt($('.scoreA').text().replace('ScoreA: ', '').trim()); const scoreB = parseInt($('.scoreB').text().replace('ScoreB: ', '').trim()); const scoreC = parseInt($('.scoreC').text().replace('ScoreC: ', '').trim()); const scoreD = parseInt($('.scoreD').text().replace('ScoreD: ', '').trim()); // 更新图表数据并重绘 radarChart.data.datasets[0].data = [scoreA, scoreB, scoreC, scoreD]; radarChart.update(); } $(document).ready(function(){ // 页面加载完成后初始化雷达图 const marksCanvas = document.getElementById("marksChart"); const marksData = { labels: ["Score A", "Score B", "Score C", "Score D"], datasets: [{ label: "城市评分", backgroundColor: "rgba(200,0,0,0.2)", borderColor: "rgba(200,0,0,1)", pointBackgroundColor: "rgba(200,0,0,1)", data: [0,0,0,0] }] }; radarChart = new Chart(marksCanvas, { type: 'radar', data: marksData, options: { scales: { r: { min: 0, max: 100 // 可根据实际分值范围调整 } } } }); $(".popup__bar__close").click(function(){ $('.popup').css('display', 'none'); mymap.flyTo([39.46975, -0.37739], 8, {easeLinearity: 0.12, duration:1}); }); });
2. 冗余代码清理
你当前HTML中加载了两次jQuery(3.3.1和2.1.3版本),会引发未知冲突,建议删除2.1.3版本的<script>引用即可。
后续适配说明
如果后续JSON新增了其他评分项,只需要做两处修改即可,不需要调整GeoJSON读取逻辑:
- 在弹窗模板
content中新增对应类名的评分元素 - 在
updateChartFromPopup函数中新增对应评分的提取逻辑,同时给雷达图的labels数组新增对应项
内容的提问来源于stack exchange,提问作者JamalDols
相关产品推荐
相关产品推荐

