React Native でチャートを描画するにはどうすればよいですか?次の記事では、React Native Echarts を使用して実際の電子商取引データ統計ページを開発する方法を紹介します。
日常のニーズに関連するグラフを作成する場合、最もよく使用されるグラフ ライブラリは echarts です。 Web 側の echart のパフォーマンスは非常に成熟しており、ミニ プログラム側にも公式ソリューションが提供されていますが、RN に対する対応するサポートはありません。市場にあるソリューションのほとんどは基本的に Webview に基づいており、私は RN に基づいたソリューションを好みますが、結局のところ、ネイティブ エクスペリエンスは Web エクスペリエンスよりも優れています。
そこで、需要に応えるために @wuba/react-native-echarts をリリースしました。実装原理に興味がある方は、ここを読んでください。
次に @wuba/react-native-echarts を使用して実際のプロジェクトでアプリケーションを作成していきます。スクリーンショットは次のとおりです:
RN開発環境をローカルにセットアップします構築手順はネット上で公開されているので割愛します。
お試しなので、expo を使って TestApp という RN プロジェクトを新規に初期化しました。
npx create-expo-app TestApp
コマンド ラインを使用して、ios android アプリ パッケージを生成します。 iOS の場合は、ここでシミュレーターを使用することをお勧めします (証明書は必要ありません)。Android の場合は、実際のマシンに接続しました
yarn android yarn ios
パッケージを生成した後、アプリケーションがインストールされたことが電話に認識されると、成功を意味します。
yarn add @wuba/react-native-echarts echarts yarn add @shopify/react-native-skia yarn add react-native-svg
既存のプロジェクトにインストールする場合は、インストール完了後に新しいパッケージを作成する必要があることに注意してください。それ以外の場合は、ネイティブの依存関係が欠落している場合にエラーが報告されます;
@wuba/react-native-echarts は 2 つのレンダリング モード (Skia と Svg) をサポートします 、最初に使用してください Skia 簡単なチャートを試してください。これは、次の小さなステップに大別できます。
具体的なコードは次のとおりです。
import { useRef, useEffect } from 'react'; import { View } from 'react-native'; /** * 一、引入echarts依赖,这里先试下折线图 */ import * as echarts from 'echarts/core'; import { LineChart } from 'echarts/charts'; import { GridComponent } from 'echarts/components'; import { SVGRenderer, SkiaChart } from '@wuba/react-native-echarts'; /** * 二、注册需要用到的组件 * SVGRenderer: 是必须注册的 * LineChart: 因为用的折线图,所以要引入LineChart(如果不知道该引入哪些组件,就直接看报错,报错说缺什么就加什么) * GridComponent: 这个就是报错的时候提示,然后我加的hhh */ echarts.use([SVGRenderer, LineChart, GridComponent]); export default () => { const skiaRef = useRef(null); // Ref用于保存图表实例 useEffect(() => { /** * 四、图表配置 */ const option = { xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], }, yAxis: { type: 'value', }, series: [ { data: [150, 230, 224, 218, 135, 147, 260], type: 'line', }, ], }; let chart; if (skiaRef.current) { /** * 五、初始化图表,指定下宽高 */ chart = echarts.init(skiaRef.current, 'light', { renderer: 'svg', width: 400, height: 400, }); chart.setOption(option); } /** * 六、页面关闭后要销毁图表实例 */ return () => chart?.dispose(); }, []); return ( <View className='index'> <SkiaChart ref={skiaRef} /> </View> ); };
書いた後、電話に接続すると、バンドルをリロードすると表示されます。 エラー レポート:
エラー不変違反: requireNativeComponent: "SkiaDomView" が UIManager に見つかりませんでした。
Google で調べたところ、次のように言われました。 ダウングレードを解決する必要がありました。実際には、expo のバージョンに対応する必要があります。依存関係をインストールするときに、次のようなプロンプトが表示されます。プロンプトが表示されたバージョンをインストールするだけです。
そこで、プロンプトに従ってバージョンを変更します。 :
@shopify/react-native-skia@0.1.157 react-native-svg@13.4.0
アプリを再構築した後、アプリは読み込まれましたが、針は刺さりませんでした; (Android はその点をカバーしており、画面幅に適応する必要があるようです)
Android | |||||||||
---|---|---|---|---|---|---|---|---|---|
##################################6、试用 Svg 模式写个复杂点的动态排序柱状图,试试 Svg 模式,给 Svg 和 Skia 做个对比,完整代码看这里。 // ...此处省略一些不重要的代码 // 注册需要用到的组件,BarChart-柱状图 LegendComponent-图例 echarts.use([SVGRenderer, BarChart, LegendComponent, GridComponent]); export default () => { const skiaRef = useRef(null); const svgRef = useRef(null); useEffect(() => { // Skia模式 const skiaChartData = getData(); // 生成图表柱状图数据 let skiaChart; let skiaInter; if (skiaRef.current) { skiaChart = echarts.init(skiaRef.current, 'light', { renderer: 'svg', width: 300, height: 300, }); skiaChart.setOption(getDefaultOption(skiaChartData)); setTimeout(function () { run(skiaChart, skiaChartData); }, 0); skiaInter = setInterval(function () { run(skiaChart, skiaChartData); }, 3000); } // Svg模式 const svgChartData = getData(); let svgChart; let svgInter; if (svgRef.current) { svgChart = echarts.init(svgRef.current, 'light', { renderer: 'svg', width: 300, height: 300, }); svgChart.setOption(getDefaultOption(svgChartData)); setTimeout(function () { run(svgChart, svgChartData); }, 0); svgInter = setInterval(function () { run(svgChart, svgChartData); }, 3000); } return () => { skiaChart?.dispose(); svgChart?.dispose(); // 定时器得清理掉,不然退出页面后还会运行 clearInterval(skiaInter); clearInterval(svgInter); }; }, []); return ( <View> <Text>skia如下</Text> <SkiaChart ref={skiaRef} /> <Text>svg如下</Text> <SvgChart ref={svgRef} /> </View> ); }; ログイン後にコピー Skia 和 Svg 模式,肉眼看不出明显差别
7、封装 Chart 组件效果不错,不过每次使用都要把一堆东西引进去好烦,先简单封装下吧 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/components'; import { SVGRenderer, SvgChart as _SvgChart, SkiaChart as _SkiaChart, } from '@wuba/react-native-echarts'; import { Dimensions } from 'react-native'; // 注册需要用到的组件 echarts.use([ DataZoomComponent, SVGRenderer, BarChart, GridComponent, LegendComponent, ToolboxComponent, TooltipComponent, TitleComponent, PieChart, LineChart, ]); // 图表默认宽高 const CHART_WIDTH = Dimensions.get('screen').width; // 默认用手机屏幕宽度 const CHART_HEIGHT = 300; const Chart = ({ option, onInit, width = CHART_WIDTH, height = CHART_HEIGHT, ChartComponent, }) => { const chartRef = useRef(null); useEffect(() => { let chart; if (chartRef.current) { chart = echarts.init(chartRef.current, 'light', { renderer: 'svg', width, height, }); option && chart.setOption(option); onInit?.(chart); } return () => chart?.dispose(); }, [option]); return <ChartComponent ref={chartRef} />; }; const SkiaChart = (props) => <Chart {...props} ChartComponent={_SkiaChart} />; const SvgChart = (props) => <Chart {...props} ChartComponent={_SvgChart} />; // 对外只暴露这哥俩就行 export { SkiaChart, SvgChart }; ログイン後にコピー 8、多个图表使用封装好了,咱就写个多图表同时使用的页面看看效果。这里写了个“电商数据分析”页面,分别有折线图、柱状图、饼图。下方是主要代码,用的 svg 模式,详细代码见这里。 // 页面代码 import { SkiaChart } from '../../components/Chart'; import { ScrollView, Text, 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 styles from './styles'; // 开启图表loading const showChartLoading = (chart) => chart.showLoading('default', { maskColor: '#305d9e', }); // 关闭图表loading const hideChartLoading = (chart) => chart.hideLoading(); export default () => { const [actual, setActual] = useState(defaultActual); // 记录实时数据 useEffect(() => { // 假设循环请求数据 const interv = setInterval(() => { const newActual = []; for (let it of actual) { newActual.push({ ...it, num: it.num + Math.floor((Math.random() * it.num) / 100), }); } setActual(newActual); }, 200); return () => clearInterval(interv); }, [actual]); const onInitLineChart = useCallback((myChart) => { showChartLoading(myChart); // 模拟数据请求 setTimeout(() => { myChart.setOption({ series: getLineData, }); hideChartLoading(myChart); }, 1000); }, []); const onInitUserChart = useCallback((myChart) => { // 模拟数据请求,跟onInitLineChart类似 }, []); const onInitSaleChart = useCallback((myChart) => { // 模拟数据请求,跟onInitLineChart类似 }, []); const onInitStatusChart = useCallback((myChart) => { // 模拟数据请求,跟onInitLineChart类似 }, []); const chartList = [ ['订单走势', lineOption, onInitLineChart], ['用户统计', userAnaly, onInitUserChart], ['各品类销售统计', salesVolume, onInitSaleChart], ['订单状态统计', salesStatus, onInitStatusChart], ]; return ( <ScrollView style={styles.index}> <StatusBar style='light' /> <View> <View style={styles.index_panel_header}> <Text style={styles.index_panel_title}>实时数据</Text> </View> <View style={styles.index_panel_content}> {actual.map(({ title, num, unit }) => ( <View key={title} style={styles.sale_item}> <View style={styles.sale_item_cell}> <Text style={styles.sale_item_text}>{title}</Text> </View> <View style={[styles.sale_item_cell, styles.num]}> <Text style={styles.sale_item_num}>{num}</Text> </View> <View style={[styles.sale_item_cell, styles.unit]}> <Text style={styles.sale_item_text}>{unit}</Text> </View> </View> ))} </View> </View> {chartList.map(([title, data, callback]) => ( <View key={title}> <View style={styles.index_panel_header}> <Text style={styles.index_panel_title}>{title}</Text> </View> <View style={styles.index_panel_content}> <SkiaChart option={data} onInit={callback} /> </View> </View> ))} </ScrollView> ); }; ログイン後にコピー 重新加载 bundle,看看效果图
渲染出来后,iOS 上交互很丝滑,安卓上交互时感觉偶尔会有卡顿(不会是因为我手机太差吧…)。 再换 Skia 模式看看 emmm 虽然可以,但是好像中文不能正常显示,安卓上中文都没有显示,iOS 则是乱码。看了下文档,目前 skia 在安卓端还不支持中文,在 iOS 端可以通过设置字体为 'PingFang SC'显示中文,比如: const option = { title: { text: '我是中文', textStyle: { fontFamily: 'PingFang SC', // 指定字体类型 }, }, }; ログイン後にコピー 但是每个显示中文的地方都要设置字体……那还是先用 svg 吧,我懒。 总结使用了一段时间后,我总结了下:
以上がecharts を使用して React Native でチャートを描画する方法について話しましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。
関連ラベル:
ソース:juejin.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
最新の問題
関連トピック
詳細>
|