React Native에서 차트를 그리는 방법은 무엇입니까? 다음 글에서는 React Native+Echarts를 활용하여 실제 전자상거래 데이터 통계 페이지를 개발하는 방법을 소개하겠습니다. 도움이 되셨으면 좋겠습니다!
일간 차트 관련 요구 사항에 가장 많이 사용되는 차트 라이브러리는 echarts입니다. 웹 측의 echarts 성능은 상당히 성숙했으며, 미니 프로그램 측에 대한 공식 솔루션도 제공되지만 RN에 대한 해당 지원은 없습니다. 시중에 나와 있는 대부분의 솔루션은 본질적으로 webview를 기반으로 하며, 저는 결국 RN 기반 솔루션을 선호합니다. 결국 웹보다 기본 경험이 더 좋을 것입니다.
그래서 우리는 수요를 충족시키기 위해 @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는 두 가지 렌더링 모드(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> ); };
작성 후 휴대폰을 흔들었고 번들을 다시 로드할 때 오류가 발생했습니다:
ERROR 불변 위반: requireNativeComponent: "SkiaDomView" was notfound in UIManager.
Google에서 다운그레이드로 해결해야 한다고 합니다. 사실, Expo 버전에 맞춰서 설치해야 하는데, 이런 메시지가 뜹니다. 버전을 설치하라는 메시지가 뜹니다
그래서 메시지에 따라 버전을 다운그레이드했습니다.
@shopify/react-native-skia@0.1.157 react-native-svg@13.4.0
앱을 다시 빌드하세요. 그리고 로드하세요 아니요, 바늘이 찌르지 않습니다. (안드로이드는 약간 커버됩니다. 화면 너비에 맞춰야 할 것 같습니다.)
iOS | Android |
---|---|
写个复杂点的动态排序柱状图,试试 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 模式,肉眼看不出明显差别
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 吧,我懒。
使用了一段时间后,我总结了下:
위 내용은 React Native에서 차트를 그리기 위해 echart를 사용하는 방법에 대해 이야기해 보겠습니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!