@wuba/react-native-echarts

repository·main·Indexed 21 days ago

https://github.com/wuba/react-native-echarts

A React Native implementation of Apache ECharts version 3.1.1 that enables high-performance rendering using react-native-svg or react-native-skia instead of a WebView. It provides SvgChart and SkiaChart components, allowing developers to register ECharts extensions and initialize charts via a ref-based API. The library includes specialized renderers (SVGRenderer and SkiaRenderer) and supports imperative methods for updating dimensions, patching children, and capturing image snapshots.

Tokens
5.6K
Snippets
17
Records
21
Agent score
75%

What's inside @wuba/react-native-echarts

  1. Choose between SvgChart and SkiaChart

    main

    To reduce bundle size, you can import only the specific renderer and chart component you intend to use instead of the main entry point.

    For SVG rendering:

    import SvgChart, { SVGRenderer } from '@wuba/react-native-echarts/svgChart';

    For Skia rendering:

    import SkiaChart, { SkiaRenderer } from '@wuba/react-native-echarts/skiaChart';
    import SvgChart, { SVGRenderer } from '@wuba/react-native-echarts/svgChart';
    // OR
    import SkiaChart, { SkiaRenderer } from '@wuba/react-native-echarts/skiaChart';
  2. How to use SvgChart or SkiaChart

    main

    The library provides two distinct rendering paths. You must choose and use only one of them to avoid conflicts.

    For SVG rendering:

    import SvgChart, { SVGRenderer } from '@wuba/react-native-echarts/svgChart';

    For Skia rendering:

    import SkiaChart, { SkiaRenderer } from '@wuba/react-native-echarts/skiaChart';
  3. Install @wuba/react-native-echarts

    main

    To install the library, use yarn to add both the core package and the echarts dependency:

    yarn add @wuba/react-native-echarts echarts

    Additionally, you must install one of the following rendering engines based on your preference:

    1. SVG: Install react-native-svg following its official installation guide.
    2. Skia: Install react-native-skia following its official installation guide.

    It is recommended to use the latest versions of echarts, react-native-svg, and react-native-skia.

  4. Implement a chart with SvgChart or SkiaChart

    main

    To render a chart, you need to:

    1. Import the chosen chart component and its corresponding renderer.
    2. Import necessary components and charts from echarts/core, echarts/charts, and echarts/components.
    3. Register the extensions using echarts.use([...]), ensuring you include the library's renderer (e.g., SVGRenderer or SkiaRenderer).
    4. Initialize the chart using echarts.init() on a ref attached to the SvgChart or SkiaChart component.
    5. Set the chart options using chart.setOption(option).
    // Choose your preferred renderer
    import { SvgChart, SVGRenderer } from '@wuba/react-native-echarts';
    import * as echarts from 'echarts/core';
    import { useRef, useEffect } from 'react';
    import { BarChart } from 'echarts/charts';
    import { TitleComponent, TooltipComponent, GridComponent } from 'echarts/components';
    
    // Register extensions
    echarts.use([
      TitleComponent,
      TooltipComponent,
      GridComponent,
      SVGRenderer,
      BarChart,
    ]);
    
    const E_HEIGHT = 250;
    const E_WIDTH = 300;
    
    function ChartComponent({ option }) {
      const chartRef = useRef<any>(null);
    
      useEffect(() => {
        let chart: any;
        if (chartRef.current) {
          // @ts-ignore
          chart = echarts.init(chartRef.current, 'light', {
            renderer: 'svg',
            width: E_WIDTH,
            height: E_HEIGHT,
          });
          chart.setOption(option);
        }
        return () => chart?.dispose();
      }, [option]);
    
      return <SvgChart ref={chartRef} />;
    }
    
    export default function App() {
      const option = {
        xAxis: {
          type: 'category',
          data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
        },
        yAxis: {
          type: 'value',
        },
        series: [
          {
            data: [120, 200, 150, 80, 70, 110, 130],
            type: 'bar',
          },
        ],
      };
      return <ChartComponent option={option} />;
    }
  5. How to use @wuba/react-native-echarts

    main

    The library provides a React Native implementation of Apache ECharts. It works by providing a chart component that acts as a container for ECharts to initialize within.

    Key steps for usage:

    1. Choose a renderer: Use either SvgChart (with SVGRenderer) or SkiaChart (with SkiaRenderer).
    2. Register components: Use echarts.use([...]) to register the necessary ECharts components (charts, components, and the specific renderer provided by this library).
    3. Initialize the chart: Use a useRef to hold a reference to the chart component. Inside a useEffect, call echarts.init() on the ref, specifying the renderer (e.g., 'svg'), and then call chart.setOption(option) to render your data.
    4. Cleanup: Always call chart.dispose() in the useEffect cleanup function to prevent memory leaks.
    import { SvgChart, SVGRenderer } from '@wuba/react-native-echarts';
    import * as echarts from 'echarts/core';
    import { useRef, useEffect } from 'react';
    import { BarChart } from 'echarts/charts';
    import { TitleComponent, TooltipComponent, GridComponent } from 'echarts/components';
    
    // 1. Register components and the renderer
    echarts.use([
      TitleComponent,
      TooltipComponent,
      GridComponent,
      SVGRenderer,
      BarChart,
    ]);
    
    const E_HEIGHT = 250;
    const E_WIDTH = 300;
    
    function ChartComponent({ option }) {
      const chartRef = useRef<any>(null);
    
      useEffect(() => {
        let chart: any;
        if (chartRef.current) {
          // 2. Initialize ECharts on the ref
          chart = echarts.init(chartRef.current, 'light', {
            renderer: 'svg',
            width: E_WIDTH,
            height: E_HEIGHT,
          });
          chart.setOption(option);
        }
        // 3. Cleanup
        return () => chart?.dispose();
      }, [option]);
    
      return <SvgChart ref={chartRef} />;
    }
    
    export default function App() {
      const option = {
        xAxis: {
          type: 'category',
          data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
        },
        yAxis: { type: 'value' },
        series: [{ data: [120, 200, 150, 80, 70, 110, 130], type: 'bar' }],
      };
      return <ChartComponent option={option} />;
    }
  6. Configure gesture handling in charts

    main

    Charts in react-native-echarts support two modes for gesture handling: using the built-in system or using react-native-gesture-handler (RNGH).

    • Built-in mode: Set useRNGH: false (or omit it). In this mode, the gesture prop cannot be provided.
    • RNGH mode: Set useRNGH: true. This allows you to pass a custom gesture configuration via the gesture prop.

    To enable or disable the internal gesture processing logic, use the handleGesture boolean prop.

    // Example of using react-native-gesture-handler with a chart
    <SkiaChart
      useRNGH={true}
      gesture={myCustomGesture}
      handleGesture={true}
    />
  7. Understand the BrushScope configuration and cache structure

    main

    A BrushScope manages several specialized caches and configuration flags to optimize the rendering of ECharts via Skia:

    Graphical Caches

    • shadowCache: Stores shadow definitions.
    • gradientCache: Stores gradient definitions.
    • patternCache: Stores pattern definitions.
    • clipPathCache: Stores SkPath objects for clipping.
    • defs: A record of SVGVNode definitions.

    CSS and Animation Management

    • cssNodes: Maps selectors to CSSSelectorVNode (Record of string to string).
    • cssAnims: Manages CSS animations.
    • cssStyleCache: Maps CSS style strings to class names for reuse.

    Configuration Flags

    • animation: Boolean indicating if animated nodes should be created.
    • emphasis: Boolean indicating if emphasis styles should be created.
    • willUpdate: Boolean used to signal if an update is occurring, which may disable certain string generation optimizations.
    • compress: Boolean to determine if the output string should be compressed.
    • ssr: Boolean for Server-Side Rendering mode.
  8. Import specific renderers for SvgChart or SkiaChart

    main

    To reduce bundle size or avoid importing unused dependencies, you can import the chart components and their corresponding renderers directly from their specific sub-paths.

    For SVG rendering: import SvgChart, { SVGRenderer } from '@wuba/react-native-echarts/svgChart';

    For Skia rendering: import SkiaChart, { SkiaRenderer } from '@wuba/react-native-echarts/skiaChart';

    // For SVG
    import SvgChart, { SVGRenderer } from '@wuba/react-native-echarts/svgChart';
    
    // For Skia
    import SkiaChart, { SkiaRenderer } from '@wuba/react-native-echarts/skiaChart';
  9. Use SvgChart for SVG-based rendering

    main

    The SvgChart component is a React component used to render ECharts via SVG. It is a memoized, forward-ref component that accepts an ECharts SVG node and styling. It supports gesture handling for interactions (like tooltips or zooming) by default.

    Key Props:

    • node: The SVGVNode representing the chart structure.
    • style: React Native style object for the container.
    • handleGesture: Boolean (default true) to enable or disable gesture handling.
    • ...gestureProps: Additional props passed to the internal GestureHandler.

    Ref API: When using a ref with SvgChart, you can access the following methods:

    • elm.patch(oldVnode, vnode): Updates the SVG node.
    • elm.setZrenderId(id): Sets the internal ZRender ID required for event dispatching.
    • dispatchEvents(types, nativeEvent, eventArgs): Manually dispatches events to ZRender.
    • getChartSize(): Returns { width, height } of the chart.
    import SvgChart from './svg/svgChart';
    
    // Usage example
    const MyChart = () => {
      const chartRef = useRef(null);
    
      return (
        <SvgChart
          ref={chartRef}
          node={echartsSvgNode} // Provided by the ECharts engine
          style={{ width: '100%', height: 400 }}
          handleGesture={true}
        />
      );
    };
  10. Configure SvgChart via Ref

    main

    To interact with the underlying chart engine or update the chart manually, you can use a ref attached to the SvgChart component. This provides access to the elm object and event dispatching capabilities.

    const chartRef = useRef(null);
    
    // ... inside a component or useEffect
    if (chartRef.current) {
      // Update the chart content
      chartRef.current.elm.patch(oldNode, newNode);
    
      // Set the ZRender ID (essential for event handling)
      chartRef.current.elm.setZrenderId(zrenderId);
    
      // Get dimensions
      const size = chartRef.current.getChartSize(); // { width, height }
    
      // Manually dispatch an event
      chartRef.current.dispatchEvents('click', nativeEvent, args);
    }
  11. Control SkiaChart via Imperative Ref

    main

    You can attach a ref to the SkiaChart component to access its imperative API. This is useful for synchronizing the chart with external logic or capturing snapshots.

    Available Ref Methods

    elm.setAttribute(name: string, value: any)

    Updates the chart dimensions. Supported names:

    • 'width': Sets the new width.
    • 'height': Sets the new height.

    elm.patch(elms: ReactElement[])

    Updates the list of children elements rendered by the chart.

    elm.setZrenderId(id: number)

    Sets the internal zrenderId required for event dispatching.

    elm.makeImageSnapshot()

    Returns a synchronous Base64 encoded PNG string of the current canvas state.

    elm.makeImageSnapshotAsync()

    Returns a Promise that resolves to a Base64 encoded PNG string of the current canvas state.

    getChartSize()

    Returns an object containing the current { width, height } of the chart.

    import React, { useRef } from 'react';
    import SkiaChart from '@wuba/react-native-echarts/src/skia/skiaChart';
    
    const MyComponent = () => {
      const chartRef = useRef<any>(null);
    
      const handleSnapshot = async () => {
        const base64Image = await chartRef.current.elm.makeImageSnapshotAsync();
        console.log('Snapshot:', base64Image);
      };
    
      const resizeChart = () => {
        chartRef.current.elm.setAttribute('width', 500);
      };
    
      return (
        <SkiaChart 
          ref={chartRef} 
          width={300} 
          height={200} 
        />
      );
    };
  12. Initialize a BrushScope with createBrushScope

    main

    The createBrushScope function initializes a BrushScope object for a given zrId. A BrushScope acts as a centralized state and cache container used during the rendering process to manage SVG nodes, CSS styles, animations, and various graphical caches (shadows, gradients, patterns, and clip paths). This is primarily used internally by the Skia rendering engine to optimize performance and manage assets.

    import { createBrushScope } from '@wuba/react-native-echarts';
    
    // zrId is a unique identifier for the ZRender instance
    const scope = createBrushScope('my-chart-id');