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

如何用服务器新数据更新Plotly.js图表?解决restyle函数失效问题

Plotly.js实时更新散点图问题解决

我尝试通过服务器SSE推送的数据实时更新Plotly.js图表,图表包含两个共享X轴的散点图。首次加载数据时图表显示正常,但后续新数据到来时,用restyle函数无法更新图表。不清楚该如何正确给restyle传参,或者是否需要用其他函数?

原实现代码

var source = new EventSource("http://old.iolab.sk/evaluation/sse/sse.php");
source.onmessage = function(event) {
    count++;
    
    if(count == 1){  // only on first data from server
        var layout = {title: "Website graph"};
        var trace1 = {
            x: [event.data.match(/\d+/g)[0]],
            y: [(event.data.match(/\d+/g)[2] + "." + event.data.match(/\d+/g)[3])],   // y1 from server
            name: "hehe",
            type: 'scatter'
          };

          var trace2 = {
            x: [event.data.match(/\d+/g)[0]],
            y: [(event.data.match(/\d+/g)[5] + "." + event.data.match(/\d+/g)[6])],   // y2 from server
            name: "hehe",
            type: 'scatter'
          };

        Plotly.newPlot("websiteGraph", [trace1, trace2], layout);
        return;
    }

    if(!isClicked){      // keeps updating the chart with data from the server until the button is clicked
        trace1 = {'x': [[event.data.match(/\d+/g)[0]]], 'y': [[(event.data.match(/\d+/g)[2] + "." + event.data.match(/\d+/g)[3])]]},
        trace2 = {'x': [[event.data.match(/\d+/g)[0]]], 'y': [[(event.data.match(/\d+/g)[5] + "." + event.data.match(/\d+/g)[6])]]};
        Plotly.restyle("websiteGraph", trace1+trace2);
    }
    return;
}

服务器返回数据格式

id: 0
data: {
data: "x": "0", 
data: "y1": "0.05", 
data: "y2": "1.03" 
data: }

id: 1
data: {
data: "x": "1", 
data: "y1": "0.077452406437284", 
data: "y2": "1.0998476951564" 
data: }

id: 2
data: {
data: "x": "2", 
data: "y1": "0.1048994967025", 
data: "y2": "1.0893908270191" 
data: }

id: 3
data: {
data: "x": "3", 
data: "y1": "0.13233595624294", 
data: "y2": "1.0086295347546" 
data: }

问题分析与修复

  1. 变量作用域错误
    第一个if块内的trace1和trace2是局部变量,外部无法访问。后续重新赋值的全局trace1/trace2和Plotly实例中的轨迹无关联,这不是正确的更新逻辑。

  2. restyle用法错误
    不能用trace1+trace2拼接对象,这会把对象强制转为字符串后拼接,完全不符合Plotly的API要求。restyle需要指定轨迹索引或批量更新参数,且实时追加数据场景下,extendTraces比restyle更适配。

  3. 数据解析方式脆弱
    用match(/\d+/g)提取数据容错性极差,服务器返回格式稍有变动就会失效。应先将服务器返回的非标准数据转换为合法JSON。

修复后的完整代码

var source = new EventSource("http://old.iolab.sk/evaluation/sse/sse.php");
var count = 0;
var isClicked = false; // 确保变量已定义

source.onmessage = function(event) {
    count++;
    
    // 处理服务器返回的非标准JSON格式
    const rawData = event.data.replace(/^data: /gm, '').trim();
    const fixedData = rawData.replace(/data: }$/, '}').replace(/,\s*$/, '');
    const parsedData = JSON.parse(fixedData);
    
    const xVal = parsedData.x;
    const y1Val = parseFloat(parsedData.y1);
    const y2Val = parseFloat(parsedData.y2);

    if(count === 1){  
        const layout = {title: "Website graph"};
        const trace1 = {
            x: [xVal],
            y: [y1Val],
            name: "Series 1",
            type: 'scatter'
        };

        const trace2 = {
            x: [xVal],
            y: [y2Val],
            name: "Series 2",
            type: 'scatter'
        };

        Plotly.newPlot("websiteGraph", [trace1, trace2], layout);
        return;
    }

    if(!isClicked){      
        // 用extendTraces追加新数据,第二个参数指定要更新的轨迹索引
        Plotly.extendTraces("websiteGraph", {
            x: [[xVal], [xVal]],
            y: [[y1Val], [y2Val]]
        }, [0, 1]);
    }
}

关键说明

  • extendTraces的参数中,x和y为二维数组,每个子数组对应一个轨迹的新数据。
  • [0,1]表示更新第0和第1个轨迹(即初始创建的trace1和trace2)。
  • 数据解析部分做了格式修复,适配服务器返回的非标准JSON,避免解析报错。
  • 修改了轨迹名称,方便区分两个散点图。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 00:20:24