paint-brush
Cách tốt nhất để thực hiện React Native Charting vào năm 2023từ tác giả@zhiqingchen
4,000 lượt đọc
4,000 lượt đọc

Cách tốt nhất để thực hiện React Native Charting vào năm 2023

từ tác giả zhiqingchen13m2023/03/30
Read on Terminal Reader

dài quá đọc không nổi

Thư viện biểu đồ được sử dụng nhiều nhất để viết các yêu cầu liên quan đến biểu đồ là **echarts**. Hiệu suất của echart trên trang web khá trưởng thành và giải pháp chính thức được cung cấp cho phía applet, nhưng không có hỗ trợ tương ứng trong RN. Trên thị trường, hầu hết tìm kiếm vẫn dựa trên bản chất của việc triển khai chế độ xem web và tôi thích chương trình dựa trên RN hơn.
featured image - Cách tốt nhất để thực hiện React Native Charting vào năm 2023
zhiqingchen HackerNoon profile picture
0-item
1-item

Thư viện biểu đồ được sử dụng nhiều nhất để viết các yêu cầu liên quan đến biểu đồ là echarts .


Hiệu suất của echart trên trang web khá trưởng thành và giải pháp chính thức được cung cấp cho phía applet, nhưng không có hỗ trợ tương ứng trong RN. Trên thị trường, hầu hết tìm kiếm vẫn dựa trên bản chất của việc triển khai chế độ xem web và tôi thích chương trình dựa trên RN hơn. Xét cho cùng, trải nghiệm bản địa sẽ tốt hơn Web.


Sau đó, tôi tìm thấy @wuba/react-native-echarts đáp ứng nhu cầu của mình, vì vậy hãy dùng thử; kết quả không tồi. Đối với những người quan tâm đến nguyên tắc thực hiện, bấm vào đây

Lời khuyên

  • Nếu bạn đã có gói APP, bạn có thể bỏ qua quy trình đóng gói trước đó và bắt đầu trực tiếp từ bước 4.
  • Mã đầy đủ cho bản dùng thử có trên GitHub tại: https://github.com/iambool/TestApp

Các bước để sử dụng nó như sau

Bước 1. Thiết lập môi trường phát triển

Đây là quá trình xây dựng môi trường phát triển RN cục bộ đã có sẵn trên Internet nên tôi sẽ không lướt qua nữa. Bạn có thể tìm kiếm nó trên Google :)

Bước 2. Tạo dự án RN

Vì đây là bản dùng thử, tôi đã sử dụng hội chợ để khởi tạo mới một dự án rn có tên là TestApp.

 npx create-expo-app TestApp 

tạo TestApp

Bước 3. Xây dựng ứng dụng trên thiết bị di động

Tạo các gói ứng dụng ios và android bằng một dòng lệnh.


iOS được khuyến nghị sử dụng trình giả lập (không cần khớp chứng chỉ). Trong khi trên Android, tôi đã kết nối với máy thật.


 yarn android yarn ios


Sau khi tạo gói, ứng dụng như bên dưới đã được cài đặt trên điện thoại, điều đó có nghĩa là nó đã thành công.

hình ảnh

Bước 4. Cài đặt các phụ thuộc liên quan

 yarn add @wuba/react-native-echarts echarts yarn add @shopify/react-native-skia yarn add react-native-svg

Lưu ý: nếu bạn đang cài đặt trong project có sẵn thì phải build gói mới sau khi cài đặt xong, nếu không thiếu local dependencies sẽ báo lỗi.

Bước 5. Thử mô hình Skia

@wuba/react-native-echarts hỗ trợ hai chế độ kết xuất (Skia và Svg) , trước tiên hãy thử một biểu đồ đơn giản với Skia.


Nó được chia thành các bước nhỏ:


  • Giới thiệu biểu đồ điện tử, thành phần biểu đồ và các thành phần phụ thuộc khác.
  • Đăng ký thành phần biểu đồ.
  • Tạo một thể hiện biểu đồ và đặt một tùy chọn.
  • Đồng bộ hóa việc hủy các phiên bản biểu đồ khi trang bị hủy.


Mã cụ thể như sau:

 import { useRef, useEffect } from 'react'; import { View } from 'react-native'; /** * 1. Import the echarts dependency, this example first tries the line chart */ import * as echarts from 'echarts/core'; import { LineChart } from 'echarts/charts'; import { GridComponent } from 'echarts/components'; import { SVGRenderer, SkiaChart } from '@wuba/react-native-echarts'; /** * 2. Register the required components * SVGRenderer: it is required to register * LineChart: because we want to show the line chart, we have to import LineChart * - If you don't know which components to import, just look at the error report and add whatever the error says is missing * GridComponent: This is the prompt when the error is reported, and then I added the, ha ha */ echarts.use([SVGRenderer, LineChart, GridComponent]); export default () => { const skiaRef = useRef(null); // Ref for saving chart instances useEffect(() => { /** * 3. chart option */ 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) { /** * 4. Initialize the chart, specifying the lower width and height */ chart = echarts.init(skiaRef.current, 'light', { renderer: 'svg', width: 400, height: 400, }); chart.setOption(option); } /** * 5. To destroy the chart instance after the page is closed */ return () => chart?.dispose(); }, []); return ( <View className='index'> <SkiaChart ref={skiaRef} /> </View> ); };


Sau khi viết code, lắc máy và tải lại gói bundle thì báo lỗi:

LỖI Vi phạm bất biến: requireNativeComponent: "SkiaDomView" không được tìm thấy trong UIManager.


Tôi đã googled nó và nó nói rằng nó yêu cầu hạ cấp phiên bản . Nó phải tương ứng với phiên bản expo, sẽ có một lời nhắc tương tự khi cài đặt phần phụ thuộc, hãy cài đặt phiên bản được nhắc và nó sẽ ổn thôi.

cảnh báo

Vì vậy, tôi đã làm theo hướng dẫn và hạ cấp phiên bản:

 @shopify/[email protected] [email protected]

Nó được tải lên sau khi xây dựng lại ứng dụng, điều này thật tuyệt. (nhưng Android che đậy điểm này, có vẻ như chiều rộng màn hình phải thích ứng.)

iOS

Android

iOS

Android

Bước 6. Thử mô hình Svg

Viết biểu đồ thanh sắp xếp động phức tạp hơn với chế độ Svg và so sánh Svg và Skia. Mã đầy đủ ở đây

 // ...Some unimportant code is omitted here // Register the required components, such as BarChart and LegendComponent echarts.use([SVGRenderer, BarChart, LegendComponent, GridComponent]); export default () => { const skiaRef = useRef(null); const svgRef = useRef(null); useEffect(() => { // Skia mode const skiaChartData = getData(); // Generate chart bar data 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 mode 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(); // The timer has to be cleaned up, otherwise it will still run after exiting the page clearInterval(skiaInter); clearInterval(svgInter); }; }, []); return ( <View> <Text>skia</Text> <SkiaChart ref={skiaRef} /> <Text>svg</Text> <SvgChart ref={svgRef} /> </View> ); };


Tôi không thể nhìn thấy sự khác biệt giữa hai chế độ này bằng chính mắt mình.

iOS

Android

hình ảnh

hình ảnh

Bước 7. Thành phần biểu đồ gói

Cho đến nay hiệu quả là khá tốt, nhưng mỗi khi tôi sử dụng một loạt thứ để nhập khẩu, nó làm phiền tôi.


Hãy kết thúc nó một cách đơn giản:

 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'; // Register the required components echarts.use([ DataZoomComponent, SVGRenderer, BarChart, GridComponent, LegendComponent, ToolboxComponent, TooltipComponent, TitleComponent, PieChart, LineChart, ]); // Default width and height of the chart const CHART_WIDTH = Dimensions.get('screen').width; // Default with the phone 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} />; // Just export these two guys export { SkiaChart, SvgChart };

Bước 8. Sử dụng nhiều biểu đồ

Sau khi hoàn thành, hãy viết một trang có nhiều biểu đồ và xem nó hoạt động như thế nào. Đây là trang dành cho “phân tích dữ liệu thương mại điện tử”, bao gồm biểu đồ đường, biểu đồ thanh và biểu đồ hình tròn. Dưới đây là mã chính được viết bằng chế độ svg, nhấp vào đây để xem mã chi tiết.


 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'; // Turn on chart loading const showChartLoading = (chart) => chart.showLoading('default', { maskColor: '#305d9e', }); // Close chart loading const hideChartLoading = (chart) => chart.hideLoading(); export default () => { const [actual, setActual] = useState(defaultActual); // Recording real-time data useEffect(() => { // Assuming a recurring request for data 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); // Simulation of data requests setTimeout(() => { myChart.setOption({ series: getLineData, }); hideChartLoading(myChart); }, 1000); }, []); const onInitUserChart = useCallback((myChart) => { // Simulate data request, similar to onInitLineChart }, []); const onInitSaleChart = useCallback((myChart) => { // Simulate data request, similar to onInitLineChart }, []); const onInitStatusChart = useCallback((myChart) => { // Simulate data request, similar to 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> ); };


Tải lại gói và xem kết quả

iOS

Android

hình ảnh

hình ảnh

Sau khi render, tương tác trên iOS rất mượt, trong khi tương tác trên Android thỉnh thoảng bị lag (không phải do máy mình quá tệ đâu nhỉ?...)


Đang thử lại chế độ Skia…

hình ảnh

Chà, mặc dù có thể, nhưng có vẻ như tiếng Trung không thể hiển thị chính xác, Android tiếng Trung không hiển thị và iOS là một mớ mã.


Sau khi đọc tài liệu, hiện tại skia không hỗ trợ tiếng Trung bên Android,


Chúng tôi có thể hiển thị tiếng Trung trên iOS bằng cách đặt phông chữ thành 'PingFang SC', ví dụ:

 const option = { title: { text: '我是中文', textStyle: { fontFamily: 'PingFang SC', // setting the font type }, }, };

Nhưng chỗ nào hiển thị tiếng Trung thì phải set font... cái đó hoặc dùng Svg trước, lười lắm.

Bản tóm tắt

Sau một thời gian sử dụng mình tóm tắt lại như sau:

  • Về mặt hỗ trợ, @wuba/react-native-echarts hỗ trợ tất cả các loại biểu đồ ngoại trừ sê-ri GL và biểu đồ bản đồ chưa được hỗ trợ, rất đủ cho công việc kinh doanh hàng ngày. Bạn có thể tìm thấy mã để triển khai các biểu đồ khác nhau trong echarts trong taro-playground .

  • Tương tác thì iOS rất mượt, Android thì thỉnh thoảng có trường hợp bị tụt khung hình.

  • Hiệu suất: Hiệu suất được báo cáo chính thức là tốt hơn các giải pháp khác.

    • Tôi đã thử, không phải lượng dữ liệu quá lớn sẽ không có vấn đề gì, nhưng khi lượng dữ liệu quá lớn (chẳng hạn như vẽ một lượng lớn bản đồ nhiệt dữ liệu), tốc độ kết xuất giảm đi rất nhiều, đó là một điểm chờ chính thức để tối ưu hóa.
    • Ngoài ra, nếu có nhiều biểu đồ trên trang, tốc độ tải sẽ chậm khi gỡ lỗi trên máy thật, vì vậy nên sử dụng trình giả lập trước.
  • Hỗ trợ tiếng Trung, chế độ Svg hỗ trợ tiếng Trung, nhưng chế độ Skia chưa khả dụng.


Trên đây chỉ là quan điểm cá nhân, mọi thắc mắc và bình luận xin mời cmt bên dưới!