1. 程式人生 > >Android專案中使用echarts

Android專案中使用echarts

寫在開始之前

之前在專案中使用過MPAndroidChart 顯示過資料圖表,現在需要使用HTML + Echart 來顯示,寫了一個Demo,DEMO中實現了線圖,餅圖,還有柱狀圖。

使用到的開源專案

  • EChart java 物件庫 這是一個針對ECharts3.x(2.x)版本的Java類庫,實現了所有ECharts中的Json結構對應的Java物件,並且可以很方便的建立Option。這個庫引用了Gson,所以build.gradle 中也要加入GSON 的依賴。
    • 版本 2.2.7

JS 和 html 編寫

為方便測試,html頁面和js程式碼放置於專案的assets 目錄中,Android程式碼訪問路徑為:file:///android_asset/jsWeb/echart.html

html 頁面編寫

  1. 在head中引入 js 指令碼,主要程式碼如下:(點選檢視全部程式碼:echart.html)
     <head>
          <!-- 匯入script -->
          <script src="http://echarts.baidu.com/echarts2/doc/example/www/js/echarts.js"></script>
         <script src="./android.js"></script>
     </head>
  2. body中請求需要的EChart指令碼,並新增對應控制元件,主要程式碼如下: (

    點選檢視全部程式碼:echart.html) 。 我在其中添加了一個js中指定資料的EChart 表格用於測試

    <div id="main" style="height:400px"></div>
     <script type="text/javascript">
             // 路徑配置
             require.config({
               paths: {
                 echarts: 'http://echarts.baidu.com/echarts2/doc/example/www/js'
                 //echarts: './www/js'
               }
             });
             // 使用
             require(
               [
                 'echarts',
                 'echarts/chart/line', // 使用柱狀圖就載入line模組,按需載入
                 'echarts/chart/bar', // 使用柱狀圖就載入bar模組,按需載入
                 'echarts/chart/pie', // 使用柱狀圖就載入pie模組,按需載入
               ],
               function (ec) {
                 // 基於準備好的dom,初始化echarts圖表
                 var myChart = ec.init(document.getElementById('main'));
                 //設定資料
                 var option = {
                 // .... 資料部分
             };
                 // 為echarts物件載入資料
                 myChart.setOption(option);
               }
             )
     </script>
    
     <hr/>
     <p>
     <b>從Android 程式碼中獲取資料繪製圖表</b><br/>
     <button onClick="loadALineChart()" style="height:40px">線狀圖</button>
     <button onClick="loadAChart(2)" style="height:40px">餅狀圖</button>
     <button onClick="loadAChart(1)" style="height:40px">柱狀圖</button>
    
     <p id="textcontent">沒有內容</p>
     <div id="chart2" style="height:400px"/>
     </p>

JS 指令碼

這裡有一點要注意:Android WebView 提供的介面返回String 型別的json option 字串,而JS 端接受到字串後需要用JSON.parse 方法轉化成js的Object 物件,只有轉換成物件之後才可以傳入到Echart的setOption 方法中顯示出來。
主要程式碼如下,點選檢視全部程式碼

        function toast(msg){
        Android.showToast(msg);
        }

        function loadALineChart(){
            // 必須加JOSN.parse 轉換資料型別
            var option = JSON.parse(Android.getLineChartOptions());

            var chart2Doc = document.getElementById('chart2');
            var myChart2 = require('echarts').init(chart2Doc);

            myChart2.setOption(option);
            document.getElementById('textcontent').innerHTML=option;
            toast(option);
        }

        /**
        type :  1 - 餅狀圖
                2 - 柱狀圖
        */
        function loadAChart(type){
            // 必須用JSON.parse() 轉換一下,才可以顯示,否則資料型別會不對
            var option = JSON.parse(Android.getPieChartOptions(type));
            var chart2Doc = document.getElementById('chart2');
            var myChart2 = require('echarts').init(chart2Doc);

            myChart2.setOption(option);
            document.getElementById('textcontent').innerHTML=option;
        }

Android 程式碼編寫

1. WebAppInterface 定義和實現

   /**
 * 注入到JS裡的物件介面
 */
class WebAppInterface {
    Context mContext;

    public WebAppInterface(Context c) {
        mContext = c;
    }

    /**
     * 獲取
     *
     * @return
     */
    @JavascriptInterface
    public String getLineChartOptions() {
        GsonOption option = markLineChartOptions();
        LogUtils.d(option.toString());
        return option.toString();
    }

    @JavascriptInterface
    public void showToast(String msg) {
        Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();
    }

    /**
     * PieChart 或者柱狀圖資料示例
     * @param type 1 - 餅狀圖資料; 2 - 柱狀圖資料
     * @return
     */
    @JavascriptInterface
    public String getPieChartOptions(int type) {

        mWebView.post(new Runnable() {
            @Override
            public void run() {
                showDialog();
            }
        });
        try {
            Thread.currentThread().sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //地址:http://echarts.baidu.com/doc/example/pie7.html
        GsonOption option = new GsonOption();
        // 設定標題
        option.title(new Title().text("某站點使用者訪問來源").subtext("純屬虛構").x(X.center));
        if(type == 2) {
            option.tooltip().trigger(Trigger.item).formatter("{a} <br/>{b} : {c} ({d}%)");
        }else  if(type == 1){
            option.tooltip().trigger(Trigger.item).formatter("{a} <br/>{b} : {c}");
        }
        // 設定圖例
        option.legend().data("直接訪問", "郵件營銷", "聯盟廣告", "視訊廣告", "搜尋引擎").orient(Orient.vertical).x(X.left);

        // 是否可以拖動以計算
        option.calculable(true);

        if(type == 2){
            // 構造資料
            Pie  pie1 = new Pie("訪問來源");
            pie1.type(SeriesType.pie).radius("45%").center("50%","60%");
            pie1.data(new Data("直接訪問",335),
                    new Data("郵件營銷",310),
                    new Data("聯盟廣告",234),
                    new Data("視訊廣告",135),
                    new Data("搜尋引擎",1548)
            );
            option.series(pie1);
        }else  if(type ==1) {
            // 構建柱狀資料
            option.xAxis(new CategoryAxis().name("訪問來源").data("視訊廣告","搜尋引擎","聯盟廣告","郵件營銷","直接訪問"));
            option.yAxis(new ValueAxis());

            Bar bar = new Bar("訪問來源");
            bar.data(11,4,14,45,67,88);
            option.series(bar);
        }
        Log.d("TAG",option.toString());
        mWebView.post(new Runnable() {
            @Override
            public void run() {
                dismissDialog();
            }
        });
        return option.toString();
    }


    @JavascriptInterface
    public GsonOption markLineChartOptions() {
        GsonOption option = new GsonOption();
        option.legend("高度(km)與氣溫(°C)變化關係");

        option.toolbox().show(true).feature(Tool.mark, Tool.dataView, new MagicType(Magic.line, Magic.bar), Tool.restore, Tool.saveAsImage);

        option.calculable(true);
        option.tooltip().trigger(Trigger.axis).formatter("Temperature : <br/>{b}km : {c}°C");

        ValueAxis valueAxis = new ValueAxis();
        valueAxis.axisLabel().formatter("{value} °C");
        option.xAxis(valueAxis);

        CategoryAxis categoryAxis = new CategoryAxis();
        categoryAxis.axisLine().onZero(false);
        categoryAxis.axisLabel().formatter("{value} km");
        categoryAxis.boundaryGap(false);
        categoryAxis.data(0, 10, 20, 30, 40, 50, 60, 70, 80);
        option.yAxis(categoryAxis);

        Line line = new Line();
        line.smooth(true).name("高度(km)與氣溫(°C)變化關係").data(15, -50, -56.5, -46.5, -22.1, -2.5, -27.7, -55.7, -76.5).itemStyle().normal().lineStyle().shadowColor("rgba(0,0,0,0.4)");
        option.series(line);
        return option;
    }
}

2. WebView 上啟用JavaScript 並注入Java物件:

     webSettings.setJavaScriptEnabled(true);
     mWebView.addJavascriptInterface(new WebAppInterface(this), "Android");