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 ( <view classname='index'> <skiachart ref={skiaref} /> </view> );};
写完摇一摇手机,reload bundle 包时出现了报错:
error invariant violation: requirenativecomponent: "skiadomview" was not found in the uimanager.
google 了一下,说是需要降级解决。其实是要跟 expo 版本对应,在安装依赖的时候也会有类似这样的提示,安装提示的版本就可以了
于是按照提示做了版本降级:
@shopify/react-native-skia@0.1.157react-native-svg@13.4.0
重新构建 app 后加载出来了,针不戳;(安卓遮住了点,看来应该自适应屏幕宽度)
iosandroid
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 模式,肉眼看不出明显差别
iosandroid
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';// 开启图表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 ( <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,看看效果图
iosandroid
渲染出来后,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画图表的详细内容。