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
Đâ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 :)
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 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.
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.
@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ỏ:
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.
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 |
---|---|
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 |
---|---|
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 };
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> ); };
iOS | Android |
---|---|
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…
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.
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.
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!