Maison > Article > interface Web > Parlons de la façon d'utiliser les graphiques électroniques pour dessiner des graphiques dans React Native
Comment dessiner des graphiques dans React Native ? L'article suivant vous présentera comment utiliser React Native+Echarts pour développer une véritable page de statistiques de données e-commerce. J'espère qu'il vous sera utile !
Pour les besoins quotidiens liés aux graphiques, la bibliothèque de graphiques la plus utilisée est echarts. Les performances des echarts côté Web sont assez matures et la solution officielle est également fournie pour le mini-programme, mais il n'y a pas de support correspondant pour RN. La plupart des solutions trouvées sur le marché sont essentiellement basées sur le webview, et je préfère les solutions basées sur RN. Après tout, l'expérience native sera meilleure que celle du web.
Nous avons donc publié @wuba/react-native-echarts pour répondre à la demande. Ceux qui sont intéressés par le principe de mise en œuvre peuvent lire ici.
Ensuite, j'utiliserai @wuba/react-native-echarts pour créer une application dans un projet réel. La capture d'écran est la suivante :
Configurer le RN. environnement de développement localement et le processus de configuration est en ligne. Une fois que vous en aurez pris une poignée, je n'entrerai pas dans les détails.
Parce qu'il s'agit d'un essai, j'ai utilisé expo pour initialiser nouvellement un projet RN appelé TestApp.
npx create-expo-app TestApp
Utilisez la ligne de commande pour générer le package d'application iOS Android. Il est recommandé d'utiliser ici un simulateur pour ios (aucun certificat requis). Pour Android, je l'ai connecté à une vraie machine
yarn android yarn ios
Après avoir généré le package, si le téléphone voit que l'application a été installée, c'est un succès.
yarn add @wuba/react-native-echarts echarts yarn add @shopify/react-native-skia yarn add react-native-svg
Notez que si vous effectuez l'installation dans un projet existant, vous devez créer un nouveau package une fois l'installation terminée, sinon une erreur sera signalée en raison du manque de dépendances natives ;
@wuba/react-native-echarts prend en charge deux modes de rendu (Skia et Svg) Essayons d'abord un graphique simple utilisant Skia. Il est grossièrement divisé en ces petites étapes :
Le code spécifique est le suivant :
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> ); };
Après avoir écrit, j'ai secoué mon téléphone et une erreur s'est produite lors du rechargement du bundle :
ERROR Violation invariante : requireNativeComponent : "SkiaDomView" n'a pas été trouvé dans l'UIManager.
Google l'a dit. Il doit être résolu par downgrading. En fait, elle doit correspondre à la version de l'expo. Lors de l'installation des dépendances, il y aura une invite comme celle-ci. Installez simplement la version demandée
J'ai donc rétrogradé la version selon les invites :
@shopify/react-native-skia@0.1.157 react-native-svg@13.4.0
Reconstruisez l'application. et chargez-le Non, l'aiguille ne pique pas ; (Android couvre un peu, il semble qu'il devrait s'adapter à la largeur de l'écran)
iOS | Android |
---|---|
效果不错,不过每次使用都要把一堆东西引进去好烦,先简单封装下吧
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 };
封装好了,咱就写个多图表同时使用的页面看看效果。这里写了个“电商数据分析”页面,分别有折线图、柱状图、饼图。下方是主要代码,用的 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 | Android |
---|---|
渲染出来后,iOS 上交互很丝滑,安卓上交互时感觉偶尔会有卡顿(不会是因为我手机太差吧…)。
再换 Skia 模式看看
emmm 虽然可以,但是好像中文不能正常显示,安卓上中文都没有显示,iOS 则是乱码。看了下文档,目前 skia 在安卓端还不支持中文,在 iOS 端可以通过设置字体为 'PingFang SC'显示中文,比如:
const option = { title: { text: '我是中文', textStyle: { fontFamily: 'PingFang SC', // 指定字体类型 }, }, };
但是每个显示中文的地方都要设置字体……那还是先用 svg 吧,我懒。
使用了一段时间后,我总结了下:
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!