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

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>

使用说明

  1. 向该模板节点发送消息时,msg.payload必须是符合格式要求的数组,示例:
[
  {"country": "USA", "value": 1200},
  {"country": "China", "value": 2500},
  {"country": "Japan", "value": 1800},
  {"country": "Germany", "value": 1500},
  {"country": "UK", "value": 1300}
]
  1. 移除了原有的setInterval自动更新逻辑,图表将仅在收到有效消息时更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 18:14:52