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

AmCharts4实现下拉选择仅展示3个年份数据系列的方案咨询

AmCharts4 实现下拉选择展示指定年份系列

实现方案

1. 核心逻辑

  • 一次性加载全量数据,通过缓存机制动态创建/切换系列,避免重复初始化组件
  • 使用HTML下拉框(或AmCharts原生下拉组件)选择3个目标年份
  • 切换时隐藏所有未选中的系列和轴,仅展示选中项

2. 完整代码实现

HTML部分(下拉选择组件)

<div style="margin-bottom: 10px;">
  <label>年份1:</label>
  <select id="year1"></select>
  <label>年份2:</label>
  <select id="year2"></select>
  <label>年份3:</label>
  <select id="year3"></select>
  <button onclick="updateChart()" style="margin-left: 10px;">更新图表</button>
</div>
<div id="chartdiv" style="width: 100%; height: 500px;"></div>

JavaScript部分(图表逻辑)

// 全局缓存:已创建的系列和轴,避免重复初始化
let seriesCache = {};
let axisCache = {};
let allYearFields = [];

// 初始化图表容器
const chart = am4core.create("chartdiv", am4charts.XYChart);
chart.dataSource.url = "ejemplodatos.php";

// 数据加载完成后初始化下拉框和默认图表
chart.dataSource.events.on("done", function(ev) {
  // 提取所有年份字段(假设字段格式为aYYYY)
  const firstDataItem = ev.target.data[0];
  allYearFields = Object.keys(firstDataItem)
    .filter(key => key.startsWith("a"))
    .map(key => ({ field: key, label: key.slice(1) }));
  
  // 填充三个下拉选择框
  populateYearSelects(allYearFields);
  
  // 默认选中最近3年
  const defaultYears = allYearFields.slice(-3);
  document.getElementById("year1").value = defaultYears[0].field;
  document.getElementById("year2").value = defaultYears[1].field;
  document.getElementById("year3").value = defaultYears[2].field;
  
  // 渲染初始图表
  updateChart();
});

// 填充下拉选择框
function populateYearSelects(yearList) {
  ["year1", "year2", "year3"].forEach(selectId => {
    const select = document.getElementById(selectId);
    select.innerHTML = "";
    yearList.forEach(year => {
      const option = document.createElement("option");
      option.value = year.field;
      option.textContent = year.label;
      select.appendChild(option);
    });
  });
}

// 复用你的系列创建逻辑,加入缓存机制
function createAxisAndSeries(field, name, opposite = false, bullet = "default") {
  // 已缓存直接返回,避免重复创建
  if (seriesCache[field]) {
    return { series: seriesCache[field], axis: axisCache[field] };
  }
  
  const valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
  if (chart.yAxes.indexOf(valueAxis) !== 0) {
    valueAxis.syncWithAxis = chart.yAxes.getIndex(0);
  }
  
  const series = chart.series.push(new am4charts.LineSeries());
  series.dataFields.valueY = field;
  series.dataFields.categoryX = "mesdia";
  series.strokeWidth = 2;
  series.name = name;
  series.tooltipText = "{name}: [bold]{valueY}[/]";
  series.minBulletDistance = 10;
  
  const interfaceColors = new am4core.InterfaceColorSet();
  switch(bullet) {
    case "triangle":
      valueAxis.renderer.line.disabled = true;
      valueAxis.renderer.labels.template.disabled = true;
      valueAxis.renderer.grid.template.disabled = true;
      
      const bulletEl = series.bullets.push(new am4charts.Bullet());
      bulletEl.width = 1;
      bulletEl.height = 1;
      bulletEl.horizontalCenter = "middle";
      bulletEl.verticalCenter = "middle";
      
      const triangle = bulletEl.createChild(am4core.Triangle);
      triangle.stroke = interfaceColors.getFor("background");
      triangle.strokeWidth = 2;
      triangle.direction = "top";
      triangle.width = 1;
      triangle.height = 1;
      break;
    default:
      const circleBullet = series.bullets.push(new am4charts.CircleBullet());
      circleBullet.circle.stroke = interfaceColors.getFor("background");
      circleBullet.width = 1;
      circleBullet.height = 1;
      circleBullet.circle.strokeWidth = 2;
      break;
  }
  
  valueAxis.renderer.line.strokeOpacity = 1;
  valueAxis.renderer.line.strokeWidth = 2;
  valueAxis.renderer.line.stroke = series.stroke;
  valueAxis.renderer.labels.template.fill = series.stroke;
  valueAxis.renderer.opposite = opposite;
  valueAxis.renderer.grid.template.disabled = true;
  
  // 缓存当前创建的系列和轴
  seriesCache[field] = series;
  axisCache[field] = valueAxis;
  
  return { series, axis };
}

// 更新图表:隐藏所有系列,仅显示选中的3个
function updateChart() {
  // 获取选中的年份字段,过滤空值
  const selectedFields = [
    document.getElementById("year1").value,
    document.getElementById("year2").value,
    document.getElementById("year3").value
  ].filter(Boolean);
  
  // 隐藏所有已创建的系列和轴
  Object.values(seriesCache).forEach(series => series.hide());
  Object.values(axisCache).forEach(axis => axis.hide());
  
  // 显示选中的系列(不存在则创建)
  selectedFields.forEach(field => {
    const yearLabel = field.slice(1);
    const { series, axis } = createAxisAndSeries(field, yearLabel);
    series.show();
    axis.show();
  });
  
  // 触发图表重绘
  chart.invalidateRawData();
}

PHP接口要求(ejemplodatos.php)

确保返回的JSON数据格式符合以下结构,包含mesdia(分类轴字段)和多个aYYYY格式的年份数值字段:

<?php
// 示例数据,实际从数据库查询获取
$data = [
  ["mesdia" => "1月", "a2024" => 120, "a2023" => 100, "a2022" => 90, "a2021" => 85],
  ["mesdia" => "2月", "a2024" => 150, "a2023" => 130, "a2022" => 110, "a2021" => 95],
  // 更多月份数据...
];

header('Content-Type: application/json');
echo json_encode($data);
?>

可选优化

  • 禁止重复选年份:在下拉框onchange事件中,移除其他下拉框已选中的选项
  • 使用AmCharts原生下拉组件:替换HTML select为AmCharts的Dropdown,风格更统一
  • 默认选中逻辑:可根据业务需求调整默认选中的年份(如最近3年、特定年份)

内容的提问来源于stack exchange,提问作者vane_bdm

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 23:00:58