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

LightningChart向现有图表系列添加数据:React下Socket实时数据绑定实现

解决方案

1. 持久化图表实例引用

首先在React组件中使用useRef存储后续需要操作的实例,避免组件重渲染时丢失引用:

import { useRef, useEffect } from 'react'
// 保持原有LightningChart相关导入不变

const YourChartComponent = () => {
  // 存储核心实例和全局常量
  const seriesRef = useRef(null)
  const xAxisRef = useRef(null)
  // 存储起始日期保证前后计算x值逻辑一致
  const startingDateRef = useRef(new Date(/* 替换为你的实际起始日期 */))
  const containerId = "你的图表容器ID"

  useEffect(() => {
    // 原有初始化逻辑放到这里
    const dateOrigin = new Date(startingDateRef.current);
    const chart = lightningChart()
      .ChartXY({
        container: containerId,
        theme: Themes.lightNew,
        columnIndex: 0,
        columnSpan: 1,
        rowIndex: 0,
        rowSpan: 1
      })
      .setTitle(containerId.split(" ")[1]);

    const originDate = new Date(moment().subtract(1, 'days'))
    const xAxis = chart.getDefaultAxisX().setTickStrategy(
      AxisTickStrategies.DateTime,
      (tickStrategy) => tickStrategy.setDateOrigin(originDate)
    );
    // 开启X轴渐进滚动策略,实现新数据进入时自动从左到右滚动
    xAxis.setScrollStrategy(AxisScrollStrategies.progressive)
    // 设定X轴视口保留的时间范围,示例为保留最近24小时数据(单位和你的x值保持一致,为毫秒)
    xAxis.setInterval(0, 24 * 60 * 60 * 1000)
    xAxisRef.current = xAxis

    const yAxis = chart
      .getDefaultAxisY()
      .fit(true)
      .setScrollStrategy(undefined)
      .setInterval(-20, 20)
      .setTitle("");

    const series = chart
      .addPointSeries({
        xAxis: xAxis,
        yAxis: yAxis,
        pointShape: PointShape.Circle
      })
      .setName("Actual");
    seriesRef.current = series

    // 原有初始数据添加逻辑保持不变
    series.add(
      sensorData.map((point) => ({
        x: new Date(point.x).getTime() - startingDateRef.current.getTime(),
        y: point.y
      }))
    )

    // 组件卸载时销毁图表
    return () => chart.dispose()
  }, [])

2. 追加Socket新数据

LightningChart的series.add()方法默认是增量追加数据,不会覆盖已有数据,直接在Socket的消息回调中按照相同的格式处理新数据后调用即可:

useEffect(() => {
    // 初始化Socket连接
    const socket = new WebSocket('替换为你的Socket服务地址')
    socket.onmessage = (event) => {
      // 若实例未初始化完成直接跳过
      if (!seriesRef.current) return
      // 解析Socket返回的新数据
      const newRawPoints = JSON.parse(event.data)
      // 格式和初始数据保持完全一致
      const formattedNewPoints = newRawPoints.map(point => ({
        x: new Date(point.x).getTime() - startingDateRef.current.getTime(),
        y: point.y
      }))
      // 直接追加数据,总点数会自动累加
      seriesRef.current.add(formattedNewPoints)
    }

    // 组件卸载时关闭Socket连接
    return () => socket.close()
  }, [])
}

补充说明

  • 不需要手动维护全局数据数组,PointSeries内部会自动存储所有已添加的数据
  • 如果需要限制总数据量避免内存占用过高,可以调用seriesRef.current.splice(0, 要删除的旧数据数量)移除最早的旧数据
  • 如果不需要自动滚动,只需要在追加数据后手动调用xAxisRef.current.setInterval(新的起始x值, 新的结束x值)自定义视口范围即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 16:45:05