前言
最近工作入坑了react-native
,有實現(xiàn)折線圖的需求,使用了阿里的antv/f2
可視化庫捂贿。
方案介紹:
- react-native-webview
- antv/f2
大概思路:
使用webview
加載本地html
文件,通過injectJavaScript
加載js
腳本
步驟
- 新建
f2chart.html
,文件較大笼吟,文件地址:f2chart.html
在ios
中, 將此文件與組件放在同一目錄吭狡,在andirod
中煞赢,手動將次文件放置在android/app/src/main/assets/f2chart.html
,如果沒有該文件夾扼睬,手動創(chuàng)建一個偷溺。
- 新建
f2Chart
組件
import React, { PureComponent, createRef } from 'react';
import { StyleSheet, Platform } from 'react-native';
import { WebView as RNWebView } from 'react-native-webview';
import renderChart, { changeChartData } from './renderChart';
const source = Platform.select({
// eslint-disable-next-line global-require
ios: require('./f2chart.html'),
android: { uri: 'file:///android_asset/f2chart.html' },
});
export default class Chart extends PureComponent {
constructor(props) {
super(props);
this.chart = createRef();
}
// eslint-disable-next-line react/no-deprecated
componentWillReceiveProps(nextProps) {
const { data } = this.props;
if (data !== nextProps.data) {
this.reload();
this.chart.current.injectJavaScript(changeChartData(nextProps));
}
}
update = data => {};
onMessage = event => {
const {
nativeEvent: { data },
} = event;
const { onChange } = this.props;
const tooltip = JSON.parse(data);
onChange(tooltip);
};
reload = () => {
this.chart.current.reload();
};
onLoadEnd = () => {
setTimeout(() => {
this.chart.current.injectJavaScript(renderChart(this.props));
}, 10);
};
render() {
const { data, ...props } = this.props;
return (
<RNWebView
scrollEnabled={false}
javaScriptEnabled
ref={this.chart}
style={styles.webView}
injectedJavaScript={renderChart(this.props)}
source={source}
onLoadEnd={this.onLoadEnd}
originWhitelist={['*']}
onMessage={this.onMessage}
{...props}
/>
);
}
}
const styles = StyleSheet.create({
webView: {
flex: 1,
backgroundColor: 'transparent',
},
});
這里需要注意的是蹋辅,在最新版本的react-native
中已經(jīng)將WebView
脫離出來了,所以需要安裝react-native-webview
yarn add react-native-webview -S
3.新建renderChart.js
export default function renderChart(props) {
const { data = [] } = props;
const chartData = data.map(c => {
return {
...c,
date: formatChartDate(c.date), // 將時間處理成 2020-03-12 12:00:00 格式
};
})
const lastData = chartData[chartData.length - 1];
const script = `
(function(){
const chart = new F2.Chart({
id: 'chart',
pixelRatio: window.devicePixelRatio,
padding: 'auto',
});
chart.source(${JSON.stringify(chartData)}, {
value: {
tickCount: 5,
min: 0,
ticks: [0, 25, 50, 75, 100],
sortable:false
},
date: {
type: 'timeCat',
range: [0, 1],
tickCount: 3,
}
});
chart.tooltip({
showCrosshairs:true,
crosshairsStyle: {
lineDash: [2]
},
alwaysShow:true,
showItemMarker: false,
background: {
radius: 2,
fill: 'rgb(229,35,97)',
padding: [ 2, 6 ]
},
tooltipMarkerStyle: {
fill: '#5B98FF', // 設(shè)置 tooltipMarker 的樣式
radius: 4,
lineWidth: 2,
stroke: '#d9e5fc',
},
onShow: function(ev) {
const items = ev.items;
const value = items[0].value;
items[0].name = null;
items[0].value = value>0?'+'+value + '元' : '0.00';
}
});
chart.axis('value', {
label: function label(text, index, total) {
const textCfg = {
text
};
return textCfg;
}
});
chart.axis('date', {
label: function label(text, index, total) {
const textArr = text.split('-');
const month = textArr[1];
const textCfg = {
color:'#888B9C',
fontSize:'10',
text:textArr[0]+'年'+parseInt(month)+'月'
};
if (index === 0) {
textCfg.textAlign = 'left';
} else if (index === total - 1) {
textCfg.textAlign = 'right';
}
return textCfg;
}
});
chart.line({
sortable: false
}).position('date*value').shape('smooth')
chart.area({
sortable: false
}).position('date*value').shape('smooth')
chart.render();
const item = ${JSON.stringify(lastData)}
const point = chart.getPosition(item);
chart.showTooltip(point);
})();
`;
return script;
}
具體配置可查詢官方API
https://f2.antv.vision/zh/docs/api/f2
4.使用
import F2LineChart from 'F2LineChart'
render(){
return(
<View>
<F2LineChart data=[] />
</View>
)
}
關(guān)于
- 文章首發(fā)于react-native 使用 F2實現(xiàn)折線圖