0

I'm wondering what's the most performant way of drawing real-time line chart with streaming data at very high frequency (new values every 15ms). I getting the data through BLE, and adding to array that I'ts never bigger then 500 items. I need to have ~10 different line charts from this data.

The whole situation is as follows: * the data stream every 15ms * i'm keeping it in redux store as array[500] (removing first element when there is new and array.length >= 500 * got to show the data as 10 independent line charts

I'm using react-native-svg-charts, works as expected but when there is 500 points and the first one is changing (as I'm removing it) the chart rerender itself and whole view gets laggy (~20fps).

I was wondering that using setNativeProps (on <Path /> from react-native-svg) will help in this scenerio, but I'm not sure is it the most performant way. If you got better ideas and suggestions (like using react-native-art) please let me know, I need to have ~60fps in this view.

Best

JJ23
  • 111
  • 8

1 Answers1

0

I answered a similar question recently here: Real-time data update chart in React Native and will suggest the same here.

I've struggled with performance when plotting in React Native with all of the SVG-based libraries I've tried, including react-native-svg-charts. I'm not sure there's much you're going to be able to do to achieve the performance you are looking for with SVG-based charts.

I recently decided to try using a couple canvas-based plotting libraries within a WebView and had very good results. I ended up making a simple package: https://www.npmjs.com/package/@dpwiese/react-native-canvas-charts.

Should you not want to use this package and instead do it yourself, it's quite straightforward. While the package source code is probably the best resource I'll summarize the steps below:

  1. Create an HTML file and import it into your component:
    const htmlTemplate = require("./index.html");
    
    where the HTML contains the JavaScript for the charting library of choice. The linked package above currently supports Chart.js v3 and uPlot. In the steps below I'll show a Chart.js configuration.
  2. Create a ref, for example let webref.
  3. Create a WebView and onLoadEnd you can inject some JavaScript into the WebView that will configure and create your chart
    <WebView
      originWhitelist={["*"]}
      ref={r  => (webref = r)}
      source={htmlTemplate}
      onLoadEnd={() => { addChart(config) }}
    />
    
    where addChart looks something like:
    const addChart = config => {
      webref.injectJavaScript(`const el = document.createElement("canvas");
        document.body.appendChild(el);
        window.canvasLine = new Chart(el.getContext('2d'), ${JSON.stringify(config)});`);
    };
    
    and config is a valid Chart.js configuration.
  4. To update the chart data simply inject some JavaScript to update the data. In the case of Chart.js here, that'd look like:
    const setData = dataSets => {
      if (dataSets) {
        dataSets.forEach((_, i) => {
          webref.injectJavaScript(`window.canvasLine.config.data.datasets[${i}].data = ${JSON.stringify(dataSets[i])};
          window.canvasLine.update();`);
        });
      }
    };
    
    where dataSets are valid Chart.js data sets.
  5. That's it! I've only played around with these two plotting libraries via the https://www.npmjs.com/package/@dpwiese/react-native-canvas-charts package, but so far performance has been really good, even with the JSON stringification of all the passed chart data. I haven't quantified it thoroughly, but both libraries are orders of magnitude more performant than any of the SVG-based ones I've tried.
Daniel Wiese
  • 131
  • 2