AmCharts3迁移至AmCharts5:自定义箱线图元素颜色实现求助
AmCharts3箱线图迁移至AmCharts5实现方案
针对你的需求,提供两种可行的实现方式,解决须线颜色、箱体分色及中位数标记的问题:
方法一:自定义CandlestickSeries实现多色箱体与须线
AmCharts5的CandlestickSeries支持对箱体、须线等元素单独配置样式,还能添加自定义中位数标记,无需堆叠多个Series:
实现步骤
- 配置箱体上下部分颜色:通过
columns.template的适配器动态判断箱体位置,返回对应颜色; - 修改须线颜色:获取箱体的
highLine(顶部须线)和lowLine(底部须线),单独设置颜色与粗细; - 添加中位数三角形标记:在每个箱体上绑定中位数数据,添加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)组合,每个部分单独设置样式:
实现步骤
- 底部须线:用LineSeries绘制最小值到下四分位数的竖线;
- 下箱体:用ColumnSeries绘制下四分位数到中位数的区域;
- 中位数标记:用Bullet添加三角形标记;
- 上箱体:用ColumnSeries绘制中位数到上四分位数的区域;
- 顶部须线:用LineSeries绘制上四分位数到最大值的竖线;
- 所有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
相关产品推荐
相关产品推荐

