You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

添加多个系列后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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 01:52:02