需求驅(qū)動(dòng)開(kāi)發(fā)受葛。
因項(xiàng)目需求题涨,需要在app中搞大量的表格。當(dāng)然相如什么charts总滩,pncharts等原生插件也可以用携栋,之前也用過(guò),但是因?yàn)樗麄兛梢哉f(shuō)沒(méi)有什么文檔咳秉,當(dāng)時(shí)踩過(guò)不少坑,純靠猜屬性是什么意思鸯隅。所以澜建,決定選擇echarts來(lái)實(shí)現(xiàn)。
但是如何使用echarts才能讓其達(dá)到跟原生一樣的體驗(yàn)蝌以,不會(huì)出現(xiàn)白屏炕舵,不會(huì)加載緩慢?
so跟畅,繼續(xù)往下看咽筋。
首先我們肯定知道,html css js什么的放到本地徊件,加載的速度肯定比下載的快奸攻,畢竟一個(gè)echarts.conmmon.min.js文件都有0.5M大小蒜危。
還有webview的選型,選擇的wkwebview睹耐,雖然wkwebview肯定是有不少坑辐赞,但是,畢竟快啊硝训。
最后一點(diǎn)响委,對(duì)于數(shù)據(jù)的獲取,如果是通用的圖表窖梁,會(huì)讓服務(wù)器來(lái)拼數(shù)據(jù)赘风。如果不是通用的圖表,我選擇在本地model中拼option纵刘,直接拿來(lái)用邀窃。
置于傳值什么的,直接走js 交互彰导,還是很簡(jiǎn)單的蛔翅。
第一步
首先自定義了一個(gè)BaseWKWebView
-(WKWebView *)webView{
if (!_webView) {
// self.userInteractionEnabled= NO;
self.userInteractionEnabled = true;
WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc]init];
configuration.preferences.javaScriptEnabled = YES;//打開(kāi)js交互
_webConfiguration = configuration;
// _jsHandler = [[XLJSHandler alloc]initWithViewController:self configuration:configuration];
_webView = [[WKWebView alloc]initWithFrame:self.bounds configuration:configuration];
[_webView setOpaque:NO];
_webView.scrollView.backgroundColor = [UIColor clearColor];
_webView.scrollView.scrollEnabled = false;
_webView.navigationDelegate = self;
_webView.backgroundColor = [UIColor clearColor];
// _webView.allowsBackForwardNavigationGestures =YES;//打開(kāi)網(wǎng)頁(yè)間的 滑動(dòng)返回
_webView.scrollView.decelerationRate = UIScrollViewDecelerationRateNormal;
// //監(jiān)控進(jìn)度
// [_webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
[self addSubview:_webView];
}
return _webView;
}
然后就開(kāi)始遇到坑了,看下面這兩個(gè)方法,就是坑所在的地方位谋,剛開(kāi)始一直用第一個(gè)方法山析,然后總是取不到css和js的路徑,最后發(fā)現(xiàn)是沒(méi)搞根目錄掏父,也就是第二個(gè)方法笋轨。
-(void)setLocalUrl:(NSString *)localUrl{
NSURL * url = [[NSBundle mainBundle] URLForResource:localUrl withExtension:@"html"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:request];
}
-(void)setLocalUrl:(NSString *)localUrl subdirectory:(NSString *)subdirectory {
NSURL * url = [[NSBundle mainBundle] URLForResource:localUrl withExtension:@"html" subdirectory:subdirectory];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:request];
}
第二步
在這里先看下服務(wù)器返回的格式 數(shù)據(jù)格式
然后根據(jù)數(shù)據(jù)格式抽了一個(gè)model出來(lái)。
@property (nonatomic, retain) NSMutableArray * target_source; // 按鈕數(shù)據(jù)源
@property (nonatomic, retain) NSMutableArray * timeAxis; // 橫坐標(biāo)
@property (nonatomic, retain) NSMutableArray * source; // 數(shù)據(jù)
在這里我們從baseWKwebView里抽個(gè)代理方法出來(lái)赊淑。然后在app中的wkwebview加載完畢的時(shí)候把數(shù)據(jù)通過(guò)js交互注入進(jìn)去爵政。
#pragma mark -- BaseWkWebViewDelegate
- (void)baseWkWebView:(BaseWKWebView *)baseWkWebView didFinishNavigation:(WKNavigation *)navigation {
[self loadBaseWKWebview:self.chartModel];
}
// 監(jiān)測(cè)數(shù)據(jù)是否取到,未取到數(shù)據(jù)隔0.4秒獲取一次
- (void)loadBaseWKWebview:(QuotesChartModel *)data {
if (!data) {
[self performSelector:@selector(loadBaseWKWebview:) withObject:self.chartModel afterDelay:0.4];
return;
}
NSString * jsonStr = [[data mj_keyValues] mj_JSONString];
[self.chartView jsFuncationName:@"setData" params:@[jsonStr]];
}
下面的是webview調(diào)用js的方法陶缺。
/**
* webview調(diào)用JS方法
*/
-(void)jsFuncationName:(NSString *)funcation params:(NSArray *)params {
NSString * params_str = [params componentsJoinedByString:@","];
NSString * js = [NSString stringWithFormat:@"%@(%@)",funcation,params_str];
[self.webView evaluateJavaScript:js completionHandler:nil];
}
第三步
該來(lái)看看放在本地的html里都是寫(xiě)的什么了钾挟。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link type="text/css" rel="stylesheet" href="./CSS/common.css">//引入css
<title>Document</title>
</head>
<body>
<script type="text/javascript" src="./modules/echarts.common.min.js"></script>//引入js文件
<div id="sc_chart" style="width: 100%;height:100%"></div>
<script type="text/javascript">
var source = [];
var timeAxis = [];
// 指定圖表的配置項(xiàng)和數(shù)據(jù)
var option = {
dataZoom:{
type:'inside'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'line',
label: {
backgroundColor: '#343A45'
}
}
},
grid:{
top:'0px',
bottom:'30px',
left:'0px',
right:'0px',
},
xAxis: {},
yAxis: [],
series: [],
animationThreshold:false
};
/**
* 設(shè)置圖數(shù)據(jù)
* keys:[key1,key2,...] 下面這個(gè)是拼接數(shù)據(jù)格式option 具體格式可以去echars官網(wǎng)去看
*/
function setKeys(keys){
// 設(shè)置圖數(shù)據(jù)
var yAxis = [];
var series = [];
keys.push({name:'默認(rèn)',key:'default',color:'#FFFFFF'})
keys.forEach((d,index) => {
if (source.hasOwnProperty(d.key)) {
var obj = source[d.key];
var color = d.color ? d.color : '#fff'
var name = obj.data['yAxis']['name'];
var unit = obj.data['yAxis']['unit'];
var yAxis_obj = {
show:false,
}
var series_obj = obj.data['series']
series_obj['symbol'] = 'circle';
series_obj['lineStyle'] = {width:0.5};
series_obj['yAxisIndex'] = index;
series_obj["itemStyle"] = {
normal:{
color:d.color,
}
},
series.push(series_obj)
yAxis.push(yAxis_obj);
}
});
option.yAxis = yAxis;
option.xAxis = {
axisLabel: {color: "#fff"},
data:timeAxis,
fontSize:9,
}
option.series = series;
var echartsDom = document.getElementById('sc_chart');
echartsDom.removeAttribute("_echarts_instance_");
var myChart = echarts.init(echartsDom);
myChart.setOption(option);
window.addEventListener('resize', function () {
myChart.resize();
})
}
function setData(data){ //webview調(diào)用的js方法注入數(shù)據(jù)
// 組裝數(shù)據(jù)
data.source.map(d=>{
source[d.key] = d;//把數(shù)據(jù)抽成一個(gè)數(shù)組里面是key value形式。
})
timeAxis = data.timeAxis;//直接給x軸
setKeys([]);//這個(gè)方法是默認(rèn)選中
}
function setOption(opt){
option = opt;
var echartsDom = document.getElementById('sc_chart');
echartsDom.removeAttribute("_echarts_instance_");
var myChart = echarts.init(echartsDom);
myChart.setOption(option);
window.addEventListener('resize', function () {
myChart.resize();
})
}
</script>
</body>
</html>
下面是具體效果饱岸。
不管是從加載速度還是響應(yīng)速度都跟原生相差無(wú)幾掺出。
當(dāng)遇到需要定制化的圖的時(shí)候,可以在本地拼接option苫费,同樣走交互傳到html中
/**
* model轉(zhuǎn)chartOption
*/
- (NSDictionary *)chartOptionByModel{
NSDictionary * option = [NSDictionary dictionary];
NSMutableArray * out_arr = [NSMutableArray array];
for (id value in self.outAxis) {
NSInteger v = 0 - [value doubleValue];
[out_arr addObject:[NSNumber numberWithInteger:v]];
};
option = @{
@"dataZoom":@{
@"type":@"inside"
},
@"tooltip":@{
@"trigger":@"axis",
@"axisPointer":@{
@"type":@"line",
}
},
@"grid":@[@{
@"left":@"0px",
@"right":@"0px",
@"bottom":@"30px",
@"top":@"0px",
}],
@"xAxis":@{@"axisLabel": @{@"color":@"#fff"},
@"data":self.timeAxis,
@"axisLine":@{@"show":[NSNumber numberWithBool:false]},
@"axisTick":@{@"show":[NSNumber numberWithBool:false]},
@"fontSize":@"9"},
@"yAxis":@[@{
@"show":[NSNumber numberWithBool:false],
@"inverse": @0,
},
@{
@"show":[NSNumber numberWithBool:false],
}],
@"series":@[@{
@"type":@"bar",
@"name": @"In",
@"stack": @"one",
@"barMaxWidth": @"60px",
@"data":self.inAxis,
@"itemStyle":@{
@"normal": @{
@"color": @"#FA5452"
},
}
},
@{
@"type":@"bar",
@"name": @"Out",
@"stack": @"one",
@"barMaxWidth": @"60px",
@"data":out_arr,
@"itemStyle":@{
@"normal": @{
@"color": @"#3CC28C"
},
}
}]
};
return option;
}
深坑更新中汤锨。。
為了實(shí)現(xiàn)這個(gè)效果
首先是push是把數(shù)組后面添加元素百框,unshift是往首位添加元素闲礼。
如果不用unshift的話(huà)就會(huì)面臨,series_obj['yAxisIndex'] 對(duì)不上的情況。