React Native中怎么畫圖表?下面本篇文章就來給大家介紹一下怎么使用React Native+Echarts開發(fā)一個真實的電商數(shù)據(jù)統(tǒng)計頁面,希望對大家有所幫助!
平時寫圖表相關(guān)需求,用得最多的圖表庫就是echarts。echarts 在 web 端的表現(xiàn)已經(jīng)相當成熟,官方對小程序端也提供了解決方案,而在 RN 方面卻沒有相應支持。市面上搜到的,大多本質(zhì)還是基于 webview 實現(xiàn),而我更傾向于基于 RN 的方案,畢竟原生的體驗會比 Web 的更好一些。
(資料圖)
所以我們發(fā)布了@wuba/react-native-echarts來滿足需求。對實現(xiàn)原理感興趣的可以看這里。
接下來我將使用 @wuba/react-native-echarts來做一個實際項目中的應用,截圖如下:
本地搭好 RN 開發(fā)環(huán)境,搭建過程網(wǎng)上一抓一大把,就不贅述了。
因為是試用,所以我用 expo 新初始化了一個 rn 工程,叫 TestApp。
npx create-expo-app TestApp
用命令行生成包 ios android app 包。這里 ios 建議用模擬器(不需要配證書),安卓我是連的真機
yarn androidyarn ios
生成包后,手機看到已經(jīng)安裝了這個應用,就代表成功啦。
yarn add @wuba/react-native-echarts echartsyarn add @shopify/react-native-skiayarn add react-native-svg
注意,如果你是在已有工程中安裝,安裝完成后要重新打個新包,不然缺少原生依賴會報錯;
@wuba/react-native-echarts 支持兩種渲染模式(Skia 和 Svg),先用 Skia 試一個簡單的圖表。大致分為這幾個小步驟:
引入 echarts、圖表組件等依賴注冊圖表組件創(chuàng)建圖表實例,并設置圖表的配置(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); } /** * 六、頁面關(guān)閉后要銷毀圖表實例 */ return () => chart?.dispose(); }, []); return ( <View className="index"> <SkiaChart ref={skiaRef} /> </View> );};寫完搖一搖手機,reload bundle 包時出現(xiàn)了報錯:
google 了一下,說是需要降級解決。其實是要跟 expo 版本對應,在安裝依賴的時候也會有類似這樣的提示,安裝提示的版本就可以了
于是按照提示做了版本降級:
@shopify/react-native-skia@0.1.157react-native-svg@13.4.0
重新構(gòu)建 app 后加載出來了,針不戳;(安卓遮住了點,看來應該自適應屏幕寬度)
| iOS | Android |
|---|---|
寫個復雜點的動態(tài)排序柱狀圖,試試 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(); // 生成圖表柱狀圖數(shù)據(jù) 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 };封裝好了,咱就寫個多圖表同時使用的頁面看看效果。這里寫了個“電商數(shù)據(jù)分析”頁面,分別有折線圖、柱狀圖、餅圖。下方是主要代碼,用的 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", });// 關(guān)閉圖表loadingconst hideChartLoading = (chart) => chart.hideLoading();export default () => { const [actual, setActual] = useState(defaultActual); // 記錄實時數(shù)據(jù) useEffect(() => { // 假設循環(huán)請求數(shù)據(jù) 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); // 模擬數(shù)據(jù)請求 setTimeout(() => { myChart.setOption({ series: getLineData, }); hideChartLoading(myChart); }, 1000); }, []); const onInitUserChart = useCallback((myChart) => { // 模擬數(shù)據(jù)請求,跟onInitLineChart類似 }, []); const onInitSaleChart = useCallback((myChart) => { // 模擬數(shù)據(jù)請求,跟onInitLineChart類似 }, []); const onInitStatusChart = useCallback((myChart) => { // 模擬數(shù)據(jù)請求,跟onInitLineChart類似 }, []); const chartList = [ ["訂單走勢", lineOption, onInitLineChart], ["用戶統(tǒng)計", userAnaly, onInitUserChart], ["各品類銷售統(tǒng)計", salesVolume, onInitSaleChart], ["訂單狀態(tài)統(tǒng)計", salesStatus, onInitStatusChart], ]; return ( <ScrollView style={styles.index}> <StatusBar style="light" /> <View> <View style={styles.index_panel_header}> <Text style={styles.index_panel_title}>實時數(shù)據(jù)</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 吧,我懶。
使用了一段時間后,我總結(jié)了下:
支持度上,@wuba/react-native-echarts 除了 GL 系列、地圖類圖表還不支持外,其余類型的圖表都支持,對于日常業(yè)務來說已經(jīng)非常 enough 了。echarts 各種類型的圖表實現(xiàn),都可以在taro-playground上找到;交互上,iOS 很絲滑,安卓有時會出現(xiàn)掉幀的情況;性能上,還挺好的。個人試了下,不是超大數(shù)據(jù)量就不會有什么問題,但是數(shù)據(jù)量太大的時候(比如畫大數(shù)據(jù)量的熱力圖),渲染速度明顯下降了很多,這是一個等待官方去優(yōu)化的點。另外頁面內(nèi)圖表多的話,真機調(diào)試時加載速度會變慢,建議先用模擬器。中文支持,Svg 模式支持中文,但 Skia 模式目前還不可以。(學習視頻分享:vuejs入門教程、編程基礎(chǔ)視頻)
以上就是聊聊React Native中怎么利用echarts畫圖表的詳細內(nèi)容,更多請關(guān)注php中文網(wǎng)其它相關(guān)文章!
關(guān)鍵詞: