最近工作入坑了react-native
,有实现折线图的需求,使用了阿里的antv/f2
可视化库。
方案介绍: – react-native-webview – antv/f2
大概思路:
使用webview
加载本地html
文件,通过injectJavaScript
加载js
脚本
f2chart.html
,文件较大,文件地址:f2chart.html在ios
中, 将此文件与组件放在同一目录,在andirod
中,手动将次文件放置在android/app/src/main/assets/f2chart.html
,如果没有该文件夹,手动创建一个。
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
中已经将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', // 设置 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>
)
}