Friday, April 12, 2024
HomeJavaScriptGlorious answer for React Native charting in 2023 | by Chenzhiqing |...

Glorious answer for React Native charting in 2023 | by Chenzhiqing | Mar, 2023


Probably the most used chart library for writing chart-related necessities is echarts. The efficiency of echarts on the web site is kind of mature, and the official answer is offered for the applet aspect, however there isn’t any corresponding help in RN. Available on the market, many of the search continues to be primarily based on the essence of the webview implementation, and I desire the RN-based program, in any case, the native expertise will likely be higher than the Internet.

so we launched @wuba/react-native-echarts to fulfill the wants. For these within the precept of implementation, click on right here.

Right this moment I’m attempting to make use of @wuba/react-native-echarts to make a real-world software just like the screenshot under.

  • If you have already got an APP package deal, you possibly can ignore the earlier packaging course of and begin instantly from step 4.
  • The total code for the trial is on GitHub at: https://github.com/iambool/TestApp

The method of constructing an area RN growth surroundings is out there on the Web, so I gained’t go over it once more. You possibly can seek for it on google 🙂

Because it was a trial, I used the expo to newly initialize an rn mission known as TestApp.

npx create-expo-app TestApp

Generate ios and android app packages with a command line. iOS is advisable to make use of the emulator (no must match the certificates), whereas Android I used to be linked to the true machine.

yarn android
yarn ios

After producing the package deal, the app just like the one under is already put in on the cellphone, which implies it’s profitable.

yarn add @wuba/react-native-echarts echarts
yarn add @shopify/react-native-skia
yarn add react-native-svg

Observe: in case you are putting in in an present mission, it’s important to construct a brand new package deal after the set up is full, in any other case the dearth of native dependencies will report an error.

@wuba/react-native-echarts helps two rendering modes (Skia and Svg), attempt a easy chart with Skia first. It’s divided into these small steps:

  • Introduce echarts, chart elements and different dependencies.
  • Registering chart elements.
  • Create a chart occasion and set an possibility.
  • Synchronized destruction of chart cases when the web page is destroyed.

The particular code is as follows:

import { useRef, useEffect } from 'react';
import { View } from 'react-native';
/**
* 1. Import the echarts dependency, this instance first tries the road chart
*/
import * as echarts from 'echarts/core';
import { LineChart } from 'echarts/charts';
import { GridComponent } from 'echarts/elements';
import { SVGRenderer, SkiaChart } from '@wuba/react-native-echarts';
/**
* 2. Register the required elements
* SVGRenderer: it's required to register
* LineChart: as a result of we need to present the road chart, we have now to import LineChart
* - If you do not know which elements to import, simply take a look at the error report and add regardless of the error says is lacking
* GridComponent: That is the immediate when the error is reported, after which I added the, ha ha
*/
echarts.use([SVGRenderer, LineChart, GridComponent]);
export default () => {
const skiaRef = useRef(null); // Ref for saving chart cases
useEffect(() => {
/**
* 3. chart possibility
*/
const possibility = {
xAxis: {
kind: 'class',
knowledge: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: {
kind: 'worth',
},
collection: [
{
data: [150, 230, 224, 218, 135, 147, 260],
kind: 'line',
},
],
};
let chart;
if (skiaRef.present) {
/**
* 4. Initialize the chart, specifying the decrease width and top
*/
chart = echarts.init(skiaRef.present, 'gentle', {
renderer: 'svg',
width: 400,
top: 400,
});
chart.setOption(possibility);
}
/**
* 5. To destroy the chart occasion after the web page is closed
*/
return () => chart?.dispose();
}, []);
return (
<View className='index'>
<SkiaChart ref={skiaRef} />
</View>
);
};

After writing the code, shaking the cellphone and reloading the bundle package deal, an error was reported:

ERROR Invariant Violation: requireNativeComponent: “SkiaDomView” was not discovered within the UIManager.

I googled it and it says it requires a model downgrade. It ought to correspond to the expo model, there will likely be an identical immediate when putting in the dependency, set up the prompted model and will probably be fantastic.

So I adopted the directions and did a model downgrade:

yarn add @shopify/react-native-skia@0.1.157
yarn add react-native-svg@13.4.0

It loaded up after rebuilding the app, which was good. (however Android covers up the purpose, evidently the display width must be adaptive.)

Write a extra advanced dynamic sorting bar chart with Svg mode, and evaluate Svg and Skia by the best way. The total code is right here

// ...Some unimportant code is omitted right here
// Register the required elements, corresponding to BarChart and LegendComponent
echarts.use([SVGRenderer, BarChart, LegendComponent, GridComponent]);
export default () => {
const skiaRef = useRef(null);
const svgRef = useRef(null);
useEffect(() => {
// Skia mode
const skiaChartData = getData(); // Generate chart bar knowledge
let skiaChart;
let skiaInter;
if (skiaRef.present) {
skiaChart = echarts.init(skiaRef.present, 'gentle', {
renderer: 'svg',
width: 300,
top: 300,
});
skiaChart.setOption(getDefaultOption(skiaChartData));
setTimeout(operate () {
run(skiaChart, skiaChartData);
}, 0);
skiaInter = setInterval(operate () {
run(skiaChart, skiaChartData);
}, 3000);
}
// Svg mode
const svgChartData = getData();
let svgChart;
let svgInter;
if (svgRef.present) {
svgChart = echarts.init(svgRef.present, 'gentle', {
renderer: 'svg',
width: 300,
top: 300,
});
svgChart.setOption(getDefaultOption(svgChartData));
setTimeout(operate () {
run(svgChart, svgChartData);
}, 0);
svgInter = setInterval(operate () {
run(svgChart, svgChartData);
}, 3000);
}
return () => {
skiaChart?.dispose();
svgChart?.dispose();
// The timer must be cleaned up, in any other case it is going to nonetheless run after exiting the web page
clearInterval(skiaInter);
clearInterval(svgInter);
};
}, []);
return (
<View>
<Textual content>skia</Textual content>
<SkiaChart ref={skiaRef} />
<Textual content>svg</Textual content>
<SvgChart ref={svgRef} />
</View>
);
};

I can’t see the distinction between these two modes with my eyes.

To this point the impact was fairly good, however each time I used a bunch of issues to import, It bothered me. Let’s wrap it up merely:

import { useRef, useEffect } from 'react';
import * as echarts from 'echarts/core';
import { BarChart, LineChart, PieChart } from 'echarts/charts';
import {
DataZoomComponent,
GridComponent,
LegendComponent,
TitleComponent,
ToolboxComponent,
TooltipComponent,
} from 'echarts/elements';
import {
SVGRenderer,
SvgChart as _SvgChart,
SkiaChart as _SkiaChart,
} from '@wuba/react-native-echarts';
import { Dimensions } from 'react-native';
// Register the required elements
echarts.use([
DataZoomComponent,
SVGRenderer,
BarChart,
GridComponent,
LegendComponent,
ToolboxComponent,
TooltipComponent,
TitleComponent,
PieChart,
LineChart,
]);
// Default width and top of the chart
const CHART_WIDTH = Dimensions.get('display').width; // Default with the cellphone display width
const CHART_HEIGHT = 300;
const Chart = ({
possibility,
onInit,
width = CHART_WIDTH,
top = CHART_HEIGHT,
ChartComponent,
}) => {
const chartRef = useRef(null);
useEffect(() => {
let chart;
if (chartRef.present) {
chart = echarts.init(chartRef.present, 'gentle', {
renderer: 'svg',
width,
top,
});
possibility && chart.setOption(possibility);
onInit?.(chart);
}
return () => chart?.dispose();
}, [option]);
return <ChartComponent ref={chartRef} />;
};
const SkiaChart = (props) => <Chart {...props} ChartComponent={_SkiaChart} />;
const SvgChart = (props) => <Chart {...props} ChartComponent={_SvgChart} />;
// Simply export these two guys
export { SkiaChart, SvgChart };

As soon as it’s wrapped, let’s write a web page with a number of charts and see the way it works. Here’s a web page for “e-commerce knowledge evaluation”, together with a line chart, bar chart and pie chart. Under is the principle code written with svg mode, click on right here for detailed code.

import { SkiaChart } from '../../elements/Chart';
import { ScrollView, Textual content, View } from 'react-native';
import { StatusBar } from 'expo-status-bar';
import { useCallback, useEffect, useState } from 'react';
import {
defaultActual,
lineOption,
salesStatus,
salesVolume,
userAnaly,
getLineData,
} from './contants';
import kinds from './kinds';
// Activate chart loading
const showChartLoading = (chart) =>
chart.showLoading('default', {
maskColor: '#305d9e',
});
// Shut chart loading
const hideChartLoading = (chart) => chart.hideLoading();
export default () => {
const [actual, setActual] = useState(defaultActual); // Recording real-time knowledge
useEffect(() => {
// Assuming a recurring request for knowledge
const interv = setInterval(() => {
const newActual = [];
for (let it of precise) {
newActual.push({
...it,
num: it.num + Math.flooring((Math.random() * it.num) / 100),
});
}
setActual(newActual);
}, 200);
return () => clearInterval(interv);
}, [actual]);
const onInitLineChart = useCallback((myChart) => {
showChartLoading(myChart);
// Simulation of knowledge requests
setTimeout(() => {
myChart.setOption({
collection: getLineData,
});
hideChartLoading(myChart);
}, 1000);
}, []);
const onInitUserChart = useCallback((myChart) => {
// Simulate knowledge request, just like onInitLineChart
}, []);
const onInitSaleChart = useCallback((myChart) => {
// Simulate knowledge request, just like onInitLineChart
}, []);
const onInitStatusChart = useCallback((myChart) => {
// Simulate knowledge request, just like onInitLineChart
}, []);
const chartList = [
['订单走势', lineOption, onInitLineChart],
['用户统计', userAnaly, onInitUserChart],
['各品类销售统计', salesVolume, onInitSaleChart],
['订单状态统计', salesStatus, onInitStatusChart],
];
return (
<ScrollView type={kinds.index}>
<StatusBar type='gentle' />
<View>
<View type={kinds.index_panel_header}>
<Textual content type={kinds.index_panel_title}>实时数据</Textual content>
</View>
<View type={kinds.index_panel_content}>
{precise.map(({ title, num, unit }) => (
<View key={title} type={kinds.sale_item}>
<View type={kinds.sale_item_cell}>
<Textual content type={kinds.sale_item_text}>{title}</Textual content>
</View>
<View type={[styles.sale_item_cell, styles.num]}>
<Textual content type={kinds.sale_item_num}>{num}</Textual content>
</View>
<View type={[styles.sale_item_cell, styles.unit]}>
<Textual content type={kinds.sale_item_text}>{unit}</Textual content>
</View>
</View>
))}
</View>
</View>
{chartList.map(([title, data, callback]) => (
<View key={title}>
<View type={kinds.index_panel_header}>
<Textual content type={kinds.index_panel_title}>{title}</Textual content>
</View>
<View type={kinds.index_panel_content}>
<SkiaChart possibility={knowledge} onInit={callback} />
</View>
</View>
))}
</ScrollView>
);
};

Reload the bundle and see the outcome

After rendering, the interplay on iOS could be very easy, whereas the interplay on Android feels sometimes laggy (not as a result of my cellphone is just too dangerous, proper?…)

Attempt Skia mode once more

Properly, though it will possibly, evidently Chinese language cannot be displayed correctly, Android Chinese language is just not displayed, and iOS is a multitude of code. After studying the documentation, skia presently doesn’t help Chinese language on the Android aspect, We will show Chinese language on iOS by setting the font to ‘PingFang SC’, for instance:

const possibility = {
title: {
textual content: '我是中文',
textStyle: {
fontFamily: 'PingFang SC', // setting the font kind
},
},
};

However each place that shows Chinese language has to set the font… that or use Svg first, I’m lazy.



RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments