『ios』echarts放到原生中所带来的极致体验。

image.png

需求驱动开发。

因项目需求,需要在app中搞大量的表格。当然相如什么charts,pncharts等原生插件也可以用,之前也用过,但是因为他们可以说没有什么文档,当时踩过不少坑,纯靠猜属性是什么意思。所以,决定选择echarts来实现。
但是如何使用echarts才能让其达到跟原生一样的体验,不会出现白屏,不会加载缓慢?
so,继续往下看。

首先我们肯定知道,html css js什么的放到本地,加载的速度肯定比下载的快,毕竟一个echarts.conmmon.min.js文件都有0.5M大小。
还有webview的选型,选择的wkwebview,虽然wkwebview肯定是有不少坑,但是,毕竟快啊。
最后一点,对于数据的获取,如果是通用的图表,会让服务器来拼数据。如果不是通用的图表,我选择在本地model中拼option,直接拿来用。
置于传值什么的,直接走js 交互,还是很简单的。

第一步

首先自定义了一个BaseWKWebView

-(WKWebView *)webView{
    if (!_webView) {
//        self.userInteractionEnabled= NO;
        self.userInteractionEnabled = true;
        WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc]init];
        configuration.preferences.javaScriptEnabled = YES;//打开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;//打开网页间的 滑动返回
        _webView.scrollView.decelerationRate = UIScrollViewDecelerationRateNormal;
//        //监控进度
//        [_webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
        [self addSubview:_webView];
    }
    return _webView;
}

然后就开始遇到坑了,看下面这两个方法,就是坑所在的地方,刚开始一直用第一个方法,然后总是取不到css和js的路径,最后发现是没搞根目录,也就是第二个方法。

-(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];
}

第二步

在这里先看下服务器返回的格式 数据格式

然后根据数据格式抽了一个model出来。

@property (nonatomic, retain) NSMutableArray * target_source;       // 按钮数据源
@property (nonatomic, retain) NSMutableArray * timeAxis;            // 横坐标
@property (nonatomic, retain) NSMutableArray * source;              // 数据

在这里我们从baseWKwebView里抽个代理方法出来。然后在app中的wkwebview加载完毕的时候把数据通过js交互注入进去。

#pragma mark -- BaseWkWebViewDelegate
- (void)baseWkWebView:(BaseWKWebView *)baseWkWebView didFinishNavigation:(WKNavigation *)navigation {
    [self loadBaseWKWebview:self.chartModel];
}

// 监测数据是否取到,未取到数据隔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调用js的方法。

/**
 *  webview调用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];
}

第三步

image.png

该来看看放在本地的html里都是写的什么了。

<!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 = [];
            // 指定图表的配置项和数据
            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
            };
        
        /**
         *  设置图数据
         *  keys:[key1,key2,...]   下面这个是拼接数据格式option   具体格式可以去echars官网去看
         */
        function setKeys(keys){
            //  设置图数据
            var yAxis = [];
            var series = [];
            keys.push({name:'默认',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调用的js方法注入数据
            //  组装数据
             data.source.map(d=>{
                 source[d.key] = d;//把数据抽成一个数组里面是key value形式。
             })
             timeAxis = data.timeAxis;//直接给x轴
             setKeys([]);//这个方法是默认选中
        }
        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>

下面是具体效果。


QQ20181010-161525-HD.gif

不管是从加载速度还是响应速度都跟原生相差无几。

当遇到需要定制化的图的时候,可以在本地拼接option,同样走交互传到html中

/**
 *  model转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;
}

深坑更新中。。

为了实现这个效果


image.png
image.png

首先是push是把数组后面添加元素,unshift是往首位添加元素。
如果不用unshift的话就会面临,series_obj['yAxisIndex'] 对不上的情况。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容