AmCharts4柱状图调用JS函数转天数为年月天格式返回NaN问题
amCharts4 柱状图自定义标签格式化天数字段解决方案
问题场景
在CakePHP4应用中使用amCharts4开发柱状图功能:
- 源数据
amount字段存储整数天数值,需要将其转换为<years> years, <months> months, <days> days格式展示,例如数值500需展示为1 year, 4 months, 15 days - 已编写可正常运行的JS转换函数
getFormatedStringFromDays(numberOfDays),传入数字/数字字符串时可返回正确格式化结果
故障表现
- 尝试通过
var mypreconvertednumber = "{values.valueX.workingValue.formatNumber('#')}";提取图表数值传入转换函数时,即使使用Number()、parseInt()做类型转换,始终得到NaN结果 - 直接给变量传入固定数字(如
var mypreconvertednumber = 500;)时,转换函数运行正常 - 已知amCharts3可通过
labelFunction配置自定义标签文本逻辑,但未找到amCharts4的对应实现
原有问题代码
barchart1.data = [{ "type": "Last Check In", "amount": 500 }, // 此处写法错误:初始化阶段占位符不会被解析 var mypreconvertednumber = "{values.valueX.workingValue.formatNumber('#')}"; var valueLabel = series.bullets.push(new am4charts.LabelBullet()); valueLabel.label.text = getFormatedStringFromDays(mypreconvertednumber); valueLabel.label.horizontalCenter = "left"; valueLabel.label.fontSize = 10; valueLabel.label.truncate = false; valueLabel.label.hideOversized = false; valueLabel.label.dx = 5;
amCharts3中参考写法:
"labelFunction": function(data) { return getFormatedStringFromDays(data); },
根本原因
amCharts的{}占位符是模板语法,只有直接赋值给组件内置支持模板解析的属性时,才会在渲染阶段被替换为真实值。在初始化代码中直接把占位符字符串传给自定义JS函数时,函数拿到的是字面量模板字符串(即完整的"{values.valueX.workingValue.formatNumber('#')}"文本),而非解析后的数值,对该字符串做数字类型转换必然返回NaN。
正确实现
amCharts4中使用属性适配器(adapter) 替代amCharts3的labelFunction,在标签渲染的实时节点拿原始数值做格式化处理,代码如下:
// 初始化柱状图数据 barchart1.data = [{ "type": "Last Check In", "amount": 500 }]; // 初始化标签子弹窗 var valueLabel = series.bullets.push(new am4charts.LabelBullet()); valueLabel.label.horizontalCenter = "left"; valueLabel.label.fontSize = 10; valueLabel.label.truncate = false; valueLabel.label.hideOversized = false; valueLabel.label.dx = 5; // 给label.text添加适配器,渲染时动态生成文本(等价于amCharts3的labelFunction) valueLabel.label.adapter.add("text", function(text, target) { // 直接从当前数据项取原始天数值,无需做格式转换再反解析 const dayValue = target.dataItem.dataContext.amount; // 传入自定义格式化函数返回最终展示文本 return getFormatedStringFromDays(dayValue); });
可选取值方式
如果需要取坐标轴映射后的值(而非直接读原始数据字段),可以通过target.dataItem.values.valueX.value拿到对应X轴的原始数值,避免格式化后反解析带来的精度问题。
内容的提问来源于stack exchange,提问作者dmc_norcal
相关产品推荐
相关产品推荐

