React Native中怎么画图表?下面本篇文章就来给大家介绍一下怎么使用React Native+Echarts开发一个真实的电商数据统计页面,希望对大家有所帮助!
平时写图表相关需求,用得最多的图表库就是echarts。echarts 在 web 端的表现已经相当成熟,官方对小程序端也提供了解决方案,而在 RN 方面却没有相应支持。市面上搜到的,大多本质还是基于 webview 实现,而我更倾向于基于 RN 的方案,毕竟原生的体验会比 Web 的更好一些。
【资料图】
所以我们发布了@wuba/react-native-echarts来满足需求。对实现原理感兴趣的可以看这里。
接下来我将使用 @wuba/react-native-echarts来做一个实际项目中的应用,截图如下:
小提示
如果你已经有 APP 包,可以忽略前面的打包流程,直接跳到第 4 步。试用的完整代码放在 github 上了,地址:github.com/iambool/Tes…详细使用过程如下
1、开发环境搭建
本地搭好 RN 开发环境,搭建过程网上一抓一大把,就不赘述了。
2、准备 RN 工程
因为是试用,所以我用 expo 新初始化了一个 rn 工程,叫 TestApp。
npx create-expo-app TestApp
登录后复制
3、build App 包
用命令行生成包 ios android app 包。这里 ios 建议用模拟器(不需要配证书),安卓我是连的真机
yarn androidyarn ios
登录后复制
生成包后,手机看到已经安装了这个应用,就代表成功啦。
4、 安装相关依赖
yarn add @wuba/react-native-echarts echartsyarn add @shopify/react-native-skiayarn add react-native-svg
登录后复制
注意,如果你是在已有工程中安装,安装完成后要重新打个新包,不然缺少原生依赖会报错;
5、试用 Skia 模式
@wuba/react-native-echarts 支持两种渲染模式(Skia 和 Svg),先用 Skia 试一个简单的图表。大致分为这几个小步骤:
引入 echarts、图表组件等依赖注册图表组件创建图表实例,并设置图表的配置(option)页面销毁时要记得同步销毁图表实例具体代码如下:
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 ( );};
登录后复制
写完摇一摇手机,reload bundle 包时出现了报错:
google 了一下,说是需要降级解决。其实是要跟 expo 版本对应,在安装依赖的时候也会有类似这样的提示,安装提示的版本就可以了
于是按照提示做了版本降级:
@shopify/react-native-skia@0.1.157react-native-svg@13.4.0
登录后复制
重新构建 app 后加载出来了,针不戳;(安卓遮住了点,看来应该自适应屏幕宽度)
iOS | 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 ( skia如下 svg如下 );};
登录后复制
Skia 和 Svg 模式,肉眼看不出明显差别
iOS | Android |
---|---|
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 ;};const SkiaChart = (props) => ;const SvgChart = (props) => ;// 对外只暴露这哥俩就行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";// 开启图表loadingconst showChartLoading = (chart) => chart.showLoading("default", { maskColor: "#305d9e", });// 关闭图表loadingconst 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 ( 实时数据 {actual.map(({ title, num, unit }) => ( {title} {num} {unit} ))} {chartList.map(([title, data, callback]) => ( {title} ))} );};
登录后复制
重新加载 bundle,看看效果图
iOS | Android |
---|---|
渲染出来后,iOS 上交互很丝滑,安卓上交互时感觉偶尔会有卡顿(不会是因为我手机太差吧…)。
再换 Skia 模式看看
emmm 虽然可以,但是好像中文不能正常显示,安卓上中文都没有显示,iOS 则是乱码。看了下文档,目前 skia 在安卓端还不支持中文,在 iOS 端可以通过设置字体为 "PingFang SC"显示中文,比如:
const option = { title: { text: "我是中文", textStyle: { fontFamily: "PingFang SC", // 指定字体类型 }, },};
登录后复制
但是每个显示中文的地方都要设置字体……那还是先用 svg 吧,我懒。
总结
使用了一段时间后,我总结了下:
支持度上,@wuba/react-native-echarts 除了 GL 系列、地图类图表还不支持外,其余类型的图表都支持,对于日常业务来说已经非常 enough 了。echarts 各种类型的图表实现,都可以在taro-playground上找到;交互上,iOS 很丝滑,安卓有时会出现掉帧的情况;性能上,还挺好的。个人试了下,不是超大数据量就不会有什么问题,但是数据量太大的时候(比如画大数据量的热力图),渲染速度明显下降了很多,这是一个等待官方去优化的点。另外页面内图表多的话,真机调试时加载速度会变慢,建议先用模拟器。中文支持,Svg 模式支持中文,但 Skia 模式目前还不可以。(学习视频分享:vuejs入门教程、编程基础视频)
以上就是聊聊React Native中怎么利用echarts画图表的详细内容,更多请关注php中文网其它相关文章!
关键词: