添加多个系列后amCharts 5地图性能不佳问题求助
amCharts 5 地图性能优化方案
问题背景
使用amCharts 5开发地图时,创建了20余个分组(多数分组仅含单个国家),每个分组单独生成MapPolygonSeries,导致地图滚动、拖拽操作卡顿生硬。
核心性能瓶颈
每个分组单独创建系列会引发以下问题:
- 重复解析
geoJSON数据28次,额外消耗计算资源 - 同时渲染近30个系列(28个分组系列+1个底图系列),大幅增加画布绘制压力
- 每个系列都绑定交互事件,事件触发时需遍历多个系列的多边形元素,导致响应延迟
优化步骤
1. 合并数据到单个系列
将所有分组数据整合为统一格式,为每个国家数据添加分组标识和对应颜色,使用单个MapPolygonSeries渲染所有高亮国家:
- 预处理
groupData,将分组名称、颜色映射到每个国家数据 - 利用系列的
fillField自动匹配颜色,避免重复创建系列
2. 实现分组Hover效果
通过数据关联实现同分组国家同步高亮:
- 监听多边形的
pointerover/pointerout事件 - 根据当前国家的分组标识,筛选同分组的所有多边形并应用状态
3. 自定义图例
单个系列无法自动生成分组图例,需手动创建图例项:
- 遍历分组数据,为每个分组创建对应的图例标记和标签
- 绑定图例的hover事件,同步地图上的分组高亮状态
4. 额外性能优化
- 使用简化版地理数据
am5geodata_worldLow_simplified,减少多边形顶点数量 - 关闭底图的交互响应,减少事件处理开销
- 降低多边形的
strokeWidth,降低绘制复杂度
优化后的完整代码
JavaScript
/** * --------------------------------------- * This demo was created using amCharts 5. * --------------------------------------- */ // 原始分组数据 var groupData = [ { "name": "G1", "data": [ { "id": "AT", "joined": "1995"}, { "id": "IE", "joined": "1973"}, ] }, { "name": "G2", "data": [ { "id": "LT", "joined": "2004" }, { "id": "LV", "joined": "2004" }, { "id": "CZ", "joined": "2004" }, { "id": "SK", "joined": "2004" }, { "id": "SI", "joined": "2004" }, { "id": "EE", "joined": "2004" }, { "id": "HU", "joined": "2004" }, { "id": "CY", "joined": "2004" }, { "id": "MT", "joined": "2004" }, { "id": "PL", "joined": "2004" } ] }, { "name": "G3", "data": [ { "id": "RO", "joined": "2007" }, { "id": "BG", "joined": "2007" } ] }, { "name": "G4", "data": [ { "id": "HR", "joined": "2013" } ] }, { "name": "G5", "data": [ { "id": "DK", "joined": "1973"}, ] }, { "name": "G6", "data": [ { "id": "FI", "joined": "1995"}, ] }, { "name": "G7", "data": [ { "id": "SE", "joined": "1995"}, ] }, { "name": "G8", "data": [ { "id": "GB", "joined": "1973"}, ] }, { "name": "G9", "data": [ { "id": "IT", "joined": "1957"}, ] }, { "name": "G10", "data": [ { "id": "FR", "joined": "1957"}, ] }, { "name": "G11", "data": [ { "id": "ES", "joined": "1986"}, ] }, { "name": "G12", "data": [ { "id": "GR", "joined": "1981"}, ] }, { "name": "G13", "data": [ { "id": "DE", "joined": "1957"}, ] }, { "name": "G14", "data": [ { "id": "BE", "joined": "1957"}, ] }, { "name": "G15", "data": [ { "id": "LU", "joined": "1957"}, ] }, { "name": "G16", "data": [ { "id": "NL", "joined": "1957"}, ] }, { "name": "G17", "data": [ { "id": "PT", "joined": "1986"} ] }, { "name": "G18", "data": [ { "id": "CZ", "joined": "2004" }, ] }, { "name": "G19", "data": [ { "id": "SK", "joined": "2004" }, ] }, { "name": "G20", "data": [ { "id": "SI", "joined": "2004" }, ] }, { "name": "G21", "data": [ { "id": "HU", "joined": "2004" }, ] }, { "name": "G22", "data": [ { "id": "CY", "joined": "2004" }, ] }, { "name": "G23", "data": [ { "id": "US", "joined": "2004" }, ] }, { "name": "G24", "data": [ { "id": "PL", "joined": "2004" } ] }, { "name": "G25", "data": [ { "id": "CA", "joined": "2004" }, ] }, { "name": "G26", "data": [ { "id": "CN", "joined": "2004" }, ] }, { "name": "G27", "data": [ { "id": "AU", "joined": "2004" }, ] }, { "name": "G28", "data": [ { "id": "BR", "joined": "2004" }, ] } ]; // 预处理数据:整合分组信息到每个国家 var countryData = []; var groupColorMap = {}; var colors = am5.ColorSet.new(root, { step: 2 }); colors.next(); // 跳过第一个颜色 am5.array.each(groupData, function(group) { var color = colors.next(); groupColorMap[group.name] = color; am5.array.each(group.data, function(country) { countryData.push({ id: country.id, joined: country.joined, group: group.name, fill: color }); }); }); // 创建根节点和图表 var root = am5.Root.new("chartdiv"); // 设置主题 root.setThemes([ am5themes_Animated.new(root) ]); // 创建地图图表 var chart = root.container.children.push(am5map.MapChart.new(root, { homeZoomLevel: 0.7, })); // 创建底图系列 var worldSeries = chart.series.push(am5map.MapPolygonSeries.new(root, { geoJSON: am5geodata_worldLow_simplified, exclude: ["AQ"] })); worldSeries.mapPolygons.template.setAll({ fill: am5.color(0xaaaaaa), interactive: false // 底图不响应交互 }); worldSeries.events.on("datavalidated", () => { chart.goHome(); }); // 创建单个高亮系列 var highlightSeries = chart.series.push(am5map.MapPolygonSeries.new(root, { geoJSON: am5geodata_worldLow_simplified, })); highlightSeries.mapPolygons.template.setAll({ tooltipText: "[bold]{name}[/]\nMember since {joined}\nGroup: {group}", interactive: true, strokeWidth: 1, fillField: "fill" }); // 创建hover状态 highlightSeries.mapPolygons.template.states.create("hover", { fill: am5.Color.brighten(am5.color(0x000000), 0.5) }); // 分组hover逻辑 highlightSeries.mapPolygons.template.events.on("pointerover", function(ev) { var targetGroup = ev.target.dataItem.dataContext.group; highlightSeries.mapPolygons.each(function(polygon) { if (polygon.dataItem.dataContext.group === targetGroup) { polygon.states.applyAnimate("hover"); } }); }); highlightSeries.mapPolygons.template.events.on("pointerout", function(ev) { highlightSeries.mapPolygons.each(function(polygon) { polygon.states.applyAnimate("default"); }); }); highlightSeries.data.setAll(countryData); // 创建自定义图例 var legend = chart.children.push(am5.Legend.new(root, { useDefaultMarker: true, centerX: am5.p50, x: am5.p50, centerY: am5.p100, y: am5.p100, dy: -20, background: am5.RoundedRectangle.new(root, { fill: am5.color(0xffffff), fillOpacity: 0.2 }) })); legend.valueLabels.template.set("forceHidden", true); // 生成图例项 var legendItems = []; am5.array.each(groupData, function(group) { legendItems.push({ name: group.name, fill: groupColorMap[group.name] }); }); legend.data.setAll(legendItems); // 图例hover同步地图高亮 const highlightGroup = (groupName) => { highlightSeries.mapPolygons.each(function(polygon) { if (polygon.dataItem.dataContext.group === groupName) { polygon.states.applyAnimate("hover"); } }); }; const resetHighlight = () => { highlightSeries.mapPolygons.each(function(polygon) { polygon.states.applyAnimate("default"); }); }; legend.labels.template.events.on("pointerover", (ev) => highlightGroup(ev.target.dataItem.dataContext.name)); legend.labels.template.events.on("pointerout", resetHighlight); legend.markers.template.events.on("pointerover", (ev) => highlightGroup(ev.target.dataItem.dataContext.name)); legend.markers.template.events.on("pointerout", resetHighlight);
CSS
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; } #chartdiv { width: 100%; height: 500px; }
HTML
<script src="https://cdn.amcharts.com/lib/5/index.js"></script> <script src="https://cdn.amcharts.com/lib/5/map.js"></script> <script src="https://cdn.amcharts.com/lib/5/geodata/worldLow_simplified.js"></script> <script src="https://cdn.amcharts.com/lib/5/themes/Animated.js"></script> <div id="chartdiv"></div>
内容的提问来源于stack exchange,提问作者smile
相关产品推荐
相关产品推荐

