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

AmCharts3迁移至AmCharts5:自定义箱线图元素颜色实现求助

AmCharts3箱线图迁移至AmCharts5实现方案

针对你的需求,提供两种可行的实现方式,解决须线颜色、箱体分色及中位数标记的问题:


方法一:自定义CandlestickSeries实现多色箱体与须线

AmCharts5的CandlestickSeries支持对箱体、须线等元素单独配置样式,还能添加自定义中位数标记,无需堆叠多个Series:

实现步骤

  1. 配置箱体上下部分颜色:通过columns.template的适配器动态判断箱体位置,返回对应颜色;
  2. 修改须线颜色:获取箱体的highLine(顶部须线)和lowLine(底部须线),单独设置颜色与粗细;
  3. 添加中位数三角形标记:在每个箱体上绑定中位数数据,添加Sprite元素作为标记,并监听轴缩放同步位置。

Vue3代码示例

<template>
  <div id="chartdiv" style="width: 100%; height: 500px"></div>
</template>

<script setup lang="ts">
import { onMounted } from 'vue';
import * as am5 from '@amcharts/amcharts5';
import * as am5xy from '@amcharts/amcharts5/xy';
import am5themes_Animated from '@amcharts/amcharts5/themes/Animated';

onMounted(() => {
  // 预处理数据,计算四分位与中位数
  let data = [
    { date: '2019-08-01', q1: 32.3, q3: 36.49, min: 31.15, max: 36.96, median: 34.4 },
    { date: '2019-08-02', q1: 31.85, q3: 35.26, min: 31.5, max: 35.95, median: 33.55 },
    { date: '2019-08-03', q1: 29.9, q3: 32.25, min: 28.3, max: 33.27, median: 31.07 },
  ];

  // 创建根实例
  let root = am5.Root.new('chartdiv');
  root.setThemes([am5themes_Animated.new(root)]);

  // 创建图表容器
  let chart = root.container.children.push(
    am5xy.XYChart.new(root, {
      focusable: true,
      panX: true,
      panY: true,
      wheelX: 'panX',
      wheelY: 'zoomX',
    })
  );

  // X轴(日期轴)
  let xAxis = chart.xAxes.push(
    am5xy.DateAxis.new(root, {
      baseInterval: { timeUnit: 'day', count: 1 },
      renderer: am5xy.AxisRendererX.new(root, {
        pan: 'zoom',
        minorGridEnabled: true,
        minGridDistance: 70,
      }),
    })
  );

  // Y轴(数值轴)
  let yAxis = chart.yAxes.push(
    am5xy.ValueAxis.new(root, {
      renderer: am5xy.AxisRendererY.new(root, { pan: 'zoom' }),
    })
  );

  // 创建箱线图Series
  let boxSeries = chart.series.push(
    am5xy.CandlestickSeries.new(root, {
      xAxis: xAxis,
      yAxis: yAxis,
      valueYField: 'q3',       // 上四分位数(箱体顶部)
      openValueYField: 'q1',   // 下四分位数(箱体底部)
      highValueYField: 'max',  // 最大值(顶部须线)
      lowValueYField: 'min',   // 最小值(底部须线)
      valueXField: 'date',
      tooltip: am5.Tooltip.new(root, {
        labelText: '最小值: {lowValueY}\n下四分位: {openValueY}\n中位数: {median}\n上四分位: {valueY}\n最大值: {highValueY}',
      }),
    })
  );

  // 1. 动态设置箱体上下部分颜色
  boxSeries.columns.template.adapters.add('fill', (fill, target) => {
    const dataItem = target.dataItem;
    if (dataItem) {
      const { median, valueY } = dataItem.dataContext;
      return valueY <= median ? am5.color(0xffff00) : am5.color(0xff9900);
    }
    return fill;
  });

  // 2. 修改须线颜色与粗细
  const highLine = boxSeries.columns.template.get('highLine');
  if (highLine) {
    highLine.set('stroke', am5.color(0xff0000));
    highLine.set('strokeWidth', 2);
  }
  const lowLine = boxSeries.columns.template.get('lowLine');
  if (lowLine) {
    lowLine.set('stroke', am5.color(0x00ff00));
    lowLine.set('strokeWidth', 2);
  }

  // 3. 添加中位数三角形标记
  boxSeries.columns.template.events.on('datavalidated', (ev) => {
    const column = ev.target;
    const dataItem = column.dataItem;
    if (dataItem) {
      const { median } = dataItem.dataContext;
      // 创建三角形Sprite
      const marker = column.children.push(
        am5.Sprite.new(root, {
          svgPath: 'M 0,-5 L 5,5 L -5,5 Z',
          fill: am5.color(0x0000ff),
          centerX: am5.percent(50),
          y: yAxis.positionToCoordinate(median),
        })
      );
      // 监听Y轴缩放,同步标记位置
      yAxis.events.on('rangechanged', () => {
        marker.set('y', yAxis.positionToCoordinate(median));
      });
    }
  });

  // 设置数据处理器与数据
  boxSeries.data.processor = am5.DataProcessor.new(root, {
    dateFields: ['date'],
    dateFormat: 'yyyy-MM-dd',
  });
  boxSeries.data.setAll(data);

  // 添加游标
  const cursor = chart.set('cursor', am5xy.XYCursor.new(root, { xAxis: xAxis }));
  cursor.lineY.set('visible', false);

  // 动画加载
  boxSeries.appear(1000, 100);
  chart.appear(1000, 100);
});
</script>

方法二:堆叠多个独立Series模拟箱线图

对应你AmCharts3的堆叠Graph思路,在AmCharts5中通过多个Series(Column+Line)组合,每个部分单独设置样式:

实现步骤

  1. 底部须线:用LineSeries绘制最小值到下四分位数的竖线;
  2. 下箱体:用ColumnSeries绘制下四分位数到中位数的区域;
  3. 中位数标记:用Bullet添加三角形标记;
  4. 上箱体:用ColumnSeries绘制中位数到上四分位数的区域;
  5. 顶部须线:用LineSeries绘制上四分位数到最大值的竖线;
  6. 所有Series设置cluster: false,确保在同一X位置叠加。

Vue3代码示例

<template>
  <div id="chartdiv" style="width: 100%; height: 500px"></div>
</template>

<script setup lang="ts">
import { onMounted } from 'vue';
import * as am5 from '@amcharts/amcharts5';
import * as am5xy from '@amcharts/amcharts5/xy';
import am5themes_Animated from '@amcharts/amcharts5/themes/Animated';

onMounted(() => {
  let data = [
    { date: '2019-08-01', q1: 32.3, q3: 36.49, min: 31.15, max: 36.96, median: 34.4 },
    { date: '2019-08-02', q1: 31.85, q3: 35.26, min: 31.5, max: 35.95, median: 33.55 },
    { date: '2019-08-03', q1: 29.9, q3: 32.25, min: 28.3, max: 33.27, median: 31.07 },
  ];

  let root = am5.Root.new('chartdiv');
  root.setThemes([am5themes_Animated.new(root)]);

  let chart = root.container.children.push(
    am5xy.XYChart.new(root, {
      focusable: true,
      panX: true,
      panY: true,
      wheelX: 'panX',
      wheelY: 'zoomX',
    })
  );

  let xAxis = chart.xAxes.push(
    am5xy.DateAxis.new(root, {
      baseInterval: { timeUnit: 'day', count: 1 },
      renderer: am5xy.AxisRendererX.new(root, {
        pan: 'zoom',
        minorGridEnabled: true,
        minGridDistance: 70,
      }),
    })
  );

  let yAxis = chart.yAxes.push(
    am5xy.ValueAxis.new(root, {
      renderer: am5xy.AxisRendererY.new(root, { pan: 'zoom' }),
    })
  );

  // 1. 底部须线(min到q1)
  const lowerWhisker = chart.series.push(
    am5xy.LineSeries.new(root, {
      xAxis: xAxis,
      yAxis: yAxis,
      valueYField: 'min',
      openValueYField: 'q1',
      valueXField: 'date',
      stroke: am5.color(0x00ff00),
      strokeWidth: 2,
      cluster: false,
    })
  );

  // 2. 下箱体(q1到median)
  const lowerBox = chart.series.push(
    am5xy.ColumnSeries.new(root, {
      xAxis: xAxis,
      yAxis: yAxis,
      valueYField: 'median',
      openValueYField: 'q1',
      valueXField: 'date',
      fill: am5.color(0xffff00),
      stroke: am5.color(0x000000),
      cluster: false,
      width: am5.percent(40),
    })
  );

  // 3. 中位数标记
  const medianMarker = chart.series.push(
    am5xy.ColumnSeries.new(root, {
      xAxis: xAxis,
      yAxis: yAxis,
      valueYField: 'median',
      valueXField: 'date',
      cluster: false,
      width: am5.percent(40),
    })
  );
  medianMarker.bullets.push(() => {
    return am5.Bullet.new(root, {
      sprite: am5.Sprite.new(root, {
        svgPath: 'M 0,-5 L 5,5 L -5,5 Z',
        fill: am5.color(0x0000ff),
        centerX: am5.percent(50),
        centerY: am5.percent(50),
      }),
    });
  });

  // 4. 上箱体(median到q3)
  const upperBox = chart.series.push(
    am5xy.ColumnSeries.new(root, {
      xAxis: xAxis,
      yAxis: yAxis,
      valueYField: 'q3',
      openValueYField: 'median',
      valueXField: 'date',
      fill: am5.color(0xff9900),
      stroke: am5.color(0x000000),
      cluster: false,
      width: am5.percent(40),
    })
  );

  // 5. 顶部须线(q3到max)
  const upperWhisker = chart.series.push(
    am5xy.LineSeries.new(root, {
      xAxis: xAxis,
      yAxis: yAxis,
      valueYField: 'q3',
      openValueYField: 'max',
      valueXField: 'date',
      stroke: am5.color(0xff0000),
      strokeWidth: 2,
      cluster: false,
    })
  );

  // 统一设置数据处理器与数据
  const dataProcessor = am5.DataProcessor.new(root, {
    dateFields: ['date'],
    dateFormat: 'yyyy-MM-dd',
  });
  [lowerWhisker, lowerBox, medianMarker, upperBox, upperWhisker].forEach(series => {
    series.data.processor = dataProcessor;
    series.data.setAll(data);
  });

  // 添加游标
  const cursor = chart.set('cursor', am5xy.XYCursor.new(root, { xAxis: xAxis }));
  cursor.lineY.set('visible', false);

  // 动画加载
  chart.appear(1000, 100);
});
</script>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 17:59:52