Node-RED Dashboard 2中AmCharts 5无法通过msg.payload更新求助
解决Node-RED Dashboard 2中通过msg.payload更新AmCharts 5图表的问题
核心修改思路
Node-RED Dashboard 2基于Vue 3,需调整模板结构和消息监听逻辑,同时确保图表实例可被消息回调访问:
- 移除冗余的完整HTML结构,适配Dashboard的嵌入环境
- 将图表关键实例暴露到全局作用域
- 通过Vue的响应式监听接收外部消息并更新图表
修改后的模板代码
<style> #chartdiv { width: 100%; height: 500px; } </style> <script src="https://cdn.amcharts.com/lib/5/index.js"></script> <script src="https://cdn.amcharts.com/lib/5/xy.js"></script> <script src="https://cdn.amcharts.com/lib/5/themes/Animated.js"></script> <div id="chartdiv"></div> <script> // 将图表核心实例提升到全局作用域,方便消息回调访问 let root, xAxis, series; am5.ready(function() { root = am5.Root.new("chartdiv"); root.setThemes([am5themes_Animated.new(root)]); const chart = root.container.children.push(am5xy.XYChart.new(root, { panX: true, panY: true, wheelX: "panX", wheelY: "zoomX", pinchZoomX: true, paddingLeft: 0, paddingRight: 1 })); const cursor = chart.set("cursor", am5xy.XYCursor.new(root, {})); cursor.lineY.set("visible", false); const xRenderer = am5xy.AxisRendererX.new(root, { minGridDistance: 30, minorGridEnabled: true }); xRenderer.labels.template.setAll({ rotation: -90, centerY: am5.p50, centerX: am5.p100, paddingRight: 15 }); xAxis = chart.xAxes.push(am5xy.CategoryAxis.new(root, { maxDeviation: 0.3, categoryField: "country", renderer: xRenderer, tooltip: am5.Tooltip.new(root, {}) })); const yRenderer = am5xy.AxisRendererY.new(root, { strokeOpacity: 0.1 }); const yAxis = chart.yAxes.push(am5xy.ValueAxis.new(root, { maxDeviation: 0.3, renderer: yRenderer })); series = chart.series.push(am5xy.ColumnSeries.new(root, { name: "Series 1", xAxis: xAxis, yAxis: yAxis, valueYField: "value", sequencedInterpolation: true, categoryXField: "country", tooltip: am5.Tooltip.new(root, { labelText: "{valueY}" }) })); series.columns.template.setAll({ cornerRadiusTL: 5, cornerRadiusTR: 5, strokeOpacity: 0 }); // 初始化数据(可选,可留空等待第一个消息) const initialData = [ { country: "USA", value: Math.floor(Math.random() * 3000) }, { country: "China", value: Math.floor(Math.random() * 3000) }, { country: "Japan", value: Math.floor(Math.random() * 3000) }, { country: "Germany", value: Math.floor(Math.random() * 3000) }, { country: "UK", value: Math.floor(Math.random() * 3000) } ]; xAxis.data.setAll(initialData); series.data.setAll(initialData); // 监听Node-RED传入的消息 scope.$watch('msg', function(newMsg) { if (newMsg && newMsg.payload) { // 验证数据格式有效性 const isValid = Array.isArray(newMsg.payload) && newMsg.payload.every(item => item.country && typeof item.value === 'number'); if (isValid) { xAxis.data.setAll(newMsg.payload); series.data.setAll(newMsg.payload); console.log('图表已更新:', newMsg.payload); } else { console.error('无效的payload格式:需为包含country(字符串)和value(数字)的对象数组'); } } }); // 加载动画 series.appear(1000); chart.appear(1000, 100); }); </script>
使用说明
- 向该模板节点发送消息时,
msg.payload必须是符合格式要求的数组,示例:
[ {"country": "USA", "value": 1200}, {"country": "China", "value": 2500}, {"country": "Japan", "value": 1800}, {"country": "Germany", "value": 1500}, {"country": "UK", "value": 1300} ]
- 移除了原有的
setInterval自动更新逻辑,图表将仅在收到有效消息时更新。
内容的提问来源于stack exchange,提问作者Hannu Metso
相关产品推荐
相关产品推荐

