作者:iambool前言平时写图表相关的需求,用的最多的图表库是echarts。echarts在web端的表现已经相当成熟,官方也为小程序端提供了解决方案,但是对RN没有相应的支持。市面上找到的大部分都是基于webview的,我更倾向于基于RN的方案。毕竟,原生体验会比web更好。所以我们发布了@wuba/react-native-echarts来满足需求。对实现原理感兴趣的可以看这里。接下来我将在实际项目中使用@wuba/react-native-echarts做一个应用。截图如下:提示如果你已经有一个APP包,可以忽略之前的打包过程。直接跳到第4步。试用的完整代码在github上,地址:https://github.com/iambool/TestApp详细使用过程如下1.搭建开发环境在本地搭建RN开发环境。反复。2.准备RN项目因为是试用,所以我用expo初始化了一个新的RN项目,叫TestApp。npxcreate-expo-appTestApp3,buildApppackage使用命令行生成packageiosandroidapppackage。这里ios推荐使用模拟器(不需要证书)。我连接的是真机yarnandroidyarnios。生成包后,手机端看到应用已经安装,即表示成功。4.安装相关依赖yarnadd@wuba/react-native-echartsechartsyarnadd@shopify/react-native-skiayarnaddreact-native-svg注意,如果是在已有项目中安装,安装后需要重新敲完整的新建包,否则缺少原生依赖会报错;5.试试Skia模式@wuba/react-native-echarts支持两种渲染模式(Skia和Svg),先用Skia试试简单的图表。大致分为这几个小步骤:??导入echarts、图表组件等,依赖注册的图表组件创建图表实例,设置图表的配置(选项)。记得在页面销毁时同步销毁图表实例。具体代码如下:import{useRef,useEffect}from'react';import{View}from'react-native';/***1.引入echarts依赖,这里先试试折线图*/import*asechartsfrom'echarts/core';import{LineChart}from'echarts/charts';import{GridComponent}from'echarts/components';import{SVGRenderer,SkiaChart}from'@wuba/react-native-echarts';/***二、需要注册的组件*SVGRenderer:必须注册*LineChart:因为用到折线图,所以必须引入LineChart(如果不知道导入哪些组件,直接看报错,加上whattheerrorsaysmissing)*GridComponent:这个是报错时的提示,然后我加了hhh*/echarts.use([SVGRenderer,LineChart,GridComponent]);exportdefault()=>{constskiaRef=使用引用(空);//Ref用于保存图表实例useEffect(()=>{/***4.图表配置*/constoption={xAxis:{type:'category',data:['Mon','Tue','Wed','Thu','Fri','Sat','Sun'],},yAxis:{type:'value',},series:[{数据:[150,230,224,218,135,147,260],输入:'线',},],};让图表;if(skiaRef.current){/***五、初始化图表,指定底部宽高*/chart=echarts.init(skiaRef.current,'light',{renderer:'svg',width:400,高度:400,});chart.setOption(选项);}/***六、图表实例应该在页面关闭后销毁*/return()=>chart?.dispose();},[]);返回();};写完后摇一摇手机重新加载bundle包出现了错误:ERRORInvariantViolation:requireNativeComponent:"SkiaDomView"wasnotfoundintheUIManager.google了一下,说需要降级才能解决问题,但是应该对应expo版本,安装依赖的时候也会有类似的提示,安装提示的版本就可以了,所以我就按照提示降了版本:@shopify/react-native-skia@0.1.157react-native-svg@13.4.0重建app加载,针不戳;(Android点覆盖了,看来应该适应屏幕宽度)iOSAndroid6,试试Svg模式写复杂点的动态排序直方图,试试Svg模式,比较Svg和Skia,完整代码看这里。//...这里省略一些不重要的代码//注册需要用到的组件,BarChart-HistogramLegendComponent-Legendecharts.use([SVGRenderer,BarChart,LegendComponent,GridComponent]);exportdefault()=>{constskiaRef=useRef(null);constsvgRef=useRef(null);useEffect(()=>{//Skia模式constskiaChartData=getData();//生成图表直方图数据letskiaChart;letskiaInter;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模式constsvgChartData=getData();letsvgChart;letsvgInter;if(svgRef.current){svgChart=echarts.init(svgRef.当前,'light',{渲染器:'svg',宽度:300,高度: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);清除间隔(svgInter);};},[]);return(skiaasbelowsvgasbelow);};Skia和Svg模式,肉眼看不出明显区别iOSAndroid7,封装Chart组件效果不错,但是每次用都要导入一堆东西很烦,简单封装一下import{useRef,useEffect}from'react';import*asechartsfrom'echarts/core';import{BarChart,LineChart,PieChart}from'echarts/charts';import{DataZoomComponent,GridComponent,LegendComponent,TitleComponent,ToolboxComponent,TooltipComponent,}from'echarts/components';import{SVGRenderer,SvgChartas_SvgChart,SkiaChartas_SkiaChart,}from'@wuba/react-native-echarts';import{Dimensions}from'react-native';//注册组件echarts必填.use([DataZoomComponent,SVGRenderer,BarChart,GridComponent,LegendComponent,ToolboxComponent,TooltipComponent,TitleComponent,PieChart,LineChart,]);//图表的默认宽高constCHART_WIDTH=Dimensions.get('screen').width;//默认手机屏幕宽度constCHART_HEIGHT=300;constChart=({option,onInit,width=CHART_WIDTH,height=CHART_HEIGHT,ChartComponent,})=>{constchartRef=useRef(null);useEffect(()=>{letchart;if(chartRef.current){chart=echarts.init(chartRef.current,'light',{renderer:'svg',width,height,});option&&chart.setOption(选项);onInit?.(图表);}return()=>chart?.dispose();},[选项]);返回;};constSkiaChart=(props)=>;constSvgChart=(props)=>;//External暴露这两兄弟就可以了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'./contents';importstylesfrom'./styles';//打开图表loadingconstshowChartLoading=(chart)=>chart.showLoading('default',{maskColor:'#305d9e',});//关闭图表loadingconsthideChartLoading=(chart)=>chart.hideLoading();exportdefault()=>{const[actual,setActual]=useState(defaultActual);//记录实时数据useEffect(()=>{//假设循环请求数据constinterv=setInterval(()=>{constnewActual=[];for(letitofactual){newActual.push({...它,num:it.num+Math.floor((Math.random()*it.num)/100),});}setActual(newActual);},200);return()=>clearInterval(interv);},[实际的]);constonInitLineChart=useCallback((myChart)=>{showChartLoading(myChart);//模拟数据请求setTimeout(()=>{myChart.setOption({series:getLineData,});hideChartLoading(myChart);},1000);},[]);constonInitUserChart=useCallback((myChart)=>{//模拟数据请求,类似onInitLineChart},[]);constonInitSaleChart=useCallback((myChart)=>{//模拟数据请求,类似onInitLineChart},[]);constonInitStatusChart=useCallback((myChart)=>{//模拟数据请求,类似onInitLineChart},[]);constchartList=[['订单趋势',lineOption,onInitLineChart],['用户统计',userAnaly,onInitUserChart],['各品类销量统计',salesVolume,onInitSaleChart],['订单状态统计',salesStatus,onInitStatusChart],];return(实时数据{actual.map(({title,num,unit})=>({title}{num}{unit}))}{chartList.map(([title,data,callback])=>(<查看样式={styles.index_panel_header}>{title}))});};重新加载包以查看渲染。iOS和Android的渲染之后,iOS上的交互很流畅,Android上的交互偶尔会感觉卡顿(不是因为我手机太差了。。。)换成Skia模式看看emmm,虽然是ok,不过好像不能正常显示中文,安卓上不显示中文,iOS是乱码。看了文档,目前skia在安卓端不支持中文。在iOS端,可以通过设置字体为'PingFangSC'来显示中文,例如:constoption={title:{text:'我是中国人',textStyle:{fontFamily:'PingFangSC',//指定字体类型},},};但是每一个显示中文的地方都要设置字体。。。那就先用svg吧,我懒。总结使用了一段时间后,总结:在支持方面,@wuba/react-native-echarts支持除GL系列和地图图表外的所有类型图表,对于日常业务来说非常不错。足够的。在taro-playground可以找到echarts的各种图表实现;交互方面,iOS很流畅,安卓有时会掉帧;在性能方面,它是相当不错的。我个人试过,数据量太大不会有问题,但是当数据量太大时(比如绘制数据量很大的热力图),渲染速度会明显下降.这是等待官方优化的一个点。另外,如果页面上的图表较多,在真机调试时加载速度会变慢。建议先使用模拟器。支持中文,Svg模式支持中文,但Skia模式暂不可用。以上仅代表个人观点,如有问题欢迎交流。