android Echart力圖webview,包含雙向交互內容

android Echart力圖webview,包含雙向交互內容

H5界面代碼

<!DOCTYPE html>
<html>
<head>
    <title>關係圖</title>
    <script src="./jquery-3.4.1.min.js"></script>
    <script src="./echarts.min.js"></script>
</head>

<body>
<div id="main" style="width:1000px;height:800px"></div>
<script type="text/javascript" charset="UTF-8">
    var myChart = echarts.init(document.getElementById('main'));
    var categories = [];

        categories[0] = {
            name: '中心節點'
        };
          categories[1] = {
            name: '上游節點'
        };
          categories[2] = {
            name: '下游節點'
        };

    var items = [];


    option = {
        // 圖的標題
        title: {
            text: '關係圖'
        },
        // 提示框的配置
        tooltip: {
            formatter: function(x) {
                return x.data.name;
            }
        },
        // 工具箱
        toolbox: {
            // 顯示工具箱
            show: true,
            feature: {
                mark: {
                    show: true
                },
                // 還原
                restore: {
                    show: true
                },
                // 保存爲圖片
                saveAsImage: {
                    show: true
                }
            }
        },
        legend: [{
            // selectedMode: 'single',
            data: categories.map(function(a) {
                return a.name;
            })
        }],

        animation: true,

        animationDurationUpdate: 1500,
        animationEasingUpdate: 'quinticInOut',

        series: [{
            type: 'graph',
<!--            type:"effectScatter", -->
            // 類型:關係圖
            layout: 'force',
            //圖的佈局,類型爲力導圖
            symbolSize: 80,
            // 調整節點的大小
            roam: true,

            legendHoverLink : true,
            focusNodeAdjacency:true,
            nodeScaleRatio : 0,
            edgeSymbol: ['circle', 'arrow'],
            edgeLabel: {
                normal: {
                    textStyle: {
                        fontSize: 20
                    }
                }
            },
            force: {
                repulsion: 3500,

                edgeLength :80,
                layoutAnimation : false

            },
            draggable: false,

            lineStyle : {
                normal : {
                    color : 'rgba(205,51,51,0.4)',
                    width : '3',
                    type : 'dotted', //線的類型 'solid'(實線)'dashed'(虛線)'dotted'(點線)
                    curveness : 0.2, //線條的曲線程度,從0到1
                    opacity : 1 // 圖形透明度。支持從 0 到 1 的數字,爲 0 時不繪製該圖形。默認0.5

                },
                emphasis : {//高亮狀態

                }
            },
            edgeLabel: {
                normal: {
                    show: true,
                    formatter: function(x) {

                    var reg = /[,,]/g;

                     return x.data.name.replace(reg,"$&\n");
                    }
                }
            },
            label: {
                normal: {
                    show: true,
                    textStyle: {},
                    formatter: function(x) {
                     return x.data.name.replace(/[^\x00-\xff]/g, "$&\x01").replace(/.{16}\x01?/g, "$&\n").replace(/\x01/g, "");
                    }
                }
            },
            // 假數據,用不到,對比看得
            data: [{
                name: 'node01',
                des: 'nodedes01',
                symbolSize: 70,
                symbol:"roundRect",
                category: 0,
            },
            {
                name: 'node02',
                des: 'nodedes02',
                symbolSize: 50,
                category: 1,
            },
            {
                name: 'node03',
                des: 'nodedes3',
                symbolSize: 50,
                category: 1,
            },
            {
                name: 'node04',
                des: 'nodedes04',
                symbolSize: 50,
                category: 1,
            },
            {
                name: 'node05',
                des: 'nodedes05',
                symbolSize: 50,
                category: 1,
            }],
            links: [{
                source: 'node01',
                target: 'node02',
                name: 'link01',
                des: 'link01des'
            },
            {
                source: 'node01',
                target: 'node03',
                name: 'link02',
                des: 'link02des'
            },
            {
                source: 'node01',
                target: 'node04',
                name: 'link03',
                des: 'link03des'
            },
            {
                source: 'node01',
                target: 'node05',
                name: 'link04',
                des: 'link05des'
            }],
            categories: categories,
        }]
    };

    myChart.on('click',function(params)
    {
        if (params.data.source != null)
        {
            callback.jumpTopicEcho(params.data.name);
        }

    });


function javaCallJs(event)
{

}
/**加載node節點**/
function loadEcharts(nodeJson)
{
    option["series"][0]["data"] = nodeJson;
}

/**加載link數據**/
function loadLinkEcharts(linkJson)
{
    option["series"][0]["links"] = linkJson;
    myChart.setOption(option);
}
</script>
</body>
</html>

承載的自定義webview


public class EchartView extends WebView {
    private static final String TAG = "EchartView";

    public EchartView(Context context) {
        this(context, null);
    }

    public EchartView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public EchartView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @SuppressLint("JavascriptInterface")
    private void init() {
        WebSettings webSettings = getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        webSettings.setSupportZoom(false);
        webSettings.setDisplayZoomControls(false);
        addJavascriptInterface(new JSCallback(), "callback");
        //直接放在android工程的assest目錄下
        loadUrl("file:///android_asset/echarts/force.html");
    }

    /**
     * 刷新echart數據
     * @param node 節點json
     * @param link link的json
     */
    public void refreshEchartsWithOption(String node, String link) {
        if (node == null || link == null) {
            return;
        }

        String call = "javascript:loadEcharts(" + node + ")";
        loadUrl(call);

        String linkCall = "javascript:loadLinkEcharts(" + link + ")";
        loadUrl(linkCall);
    }

}

H5調用android的方法類

/**
 * H5調用方法類
 */
public class JSCallback extends Object
{

    @JavascriptInterface
    public void jumpTopicEcho(String topic)
    {
    	//獲取當前所在的activity
        final Activity activity = MyActivityManager.getInstance().getCurrentActivity();
        if (activity != null)
        {
            final String[] split = topic.split(",");//以逗號分割
            AlertDialog alertDialog = new AlertDialog
                    .Builder(activity)
                    .setItems(split, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                        	//根據選擇跳轉其他activity
                            Intent intent = new Intent(activity,TopicMsgActivity.class);
                            intent.putExtra("topic",split[which]);
                            activity.startActivity(intent);
                        }
                    }).create();
            alertDialog.show();
        }

    }
}

具體使用方法實例

/**
 * 力圖的activity
 */
public class EChartsActivity extends AppCompatActivity
{

    private EchartView webView;

    private List<NodeInfo> nodeInfos = new ArrayList<>();

    private List<LinkInfo> linkInfos = new ArrayList<>();

    //上游節點
    private List<String> upStreamNodes = new ArrayList<>();

    //根節點
    private NodeInfo rootNode;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.echarts_activity);
        getData();
        webView = findViewById(R.id.chart_view);
        webView.setWebViewClient(new WebViewClient()
        {
            @Override
            public void onPageFinished(WebView view, String url)
            {
                super.onPageFinished(view, url);
                //最好在h5頁面加載完畢後再加載數據,防止html的標籤還未加載完成,不能正常顯示
                EChartsDataTask task = new EChartsDataTask("zzkk");
                task.execute();
            }
        });
    }

    private void getData()
    {
       //todo 獲取數據
    }


    private class EChartsDataTask extends AsyncTask<Object, Integer, Object>
    {
        private String params;

        public EChartsDataTask(String params)
        {
            this.params = params;
        }

        @Override
        protected Object doInBackground(Object... objects)
        {
            //添加返回數據
            nodeInfos.clear();
            nodeInfos.addAll(JNIUtils.getNodesFromJNI(params));

            linkInfos.clear();
            linkInfos.addAll(JNIUtils.getLinkFromJNI(params));
            return null;
        }

        @Override
        protected void onPostExecute(Object o)
        {
            super.onPostExecute(o);
            if (!nodeInfos.isEmpty() && !linkInfos.isEmpty())
            {
                rootNode = nodeInfos.get(0);
                // 需要拼接成json數據
                String link = getLinkBuffer().toString();
                String node = getNodeBuffer().toString();
                Log.d("zzkk", "node = " + node);
                Log.d("zzkk", "link = " + link);
                //h5界面刷新數據
                webView.refreshEchartsWithOption(node, link);
            }
        }
    }

    private StringBuffer getLinkBuffer()
    {
        StringBuffer linkBuffer = new StringBuffer();
        linkBuffer.append("[" + "\n");
        upStreamNodes.clear();
        for (int i = 0; i < linkInfos.size(); i++)
        {
            LinkInfo info = linkInfos.get(i);
            // 如果目標節點是根節點,添加至上游列表中
            if (rootNode.name.equals(info.target))
            {
                upStreamNodes.add(info.source);
            }
            if (i == linkInfos.size() - 1)
            {

                linkBuffer.append("{" + "\n");
                linkBuffer.append("source : " + "'" + info.source + "'," + "\n");
                linkBuffer.append("target : " + "'" + info.target + "'," + "\n");
                linkBuffer.append("name : " + "'" + "topic1, topic2, " +
                        "topic3" + "'," +
                        "\n");
                linkBuffer.append("des : " + "'" + info.desc + "'" + "\n");
                linkBuffer.append("}" + "\n");
            }

            else
            {
                linkBuffer.append("{" + "\n");
                linkBuffer.append("source : " + "'" + info.source + "'," + "\n");
                linkBuffer.append("target : " + "'" + info.target + "'," + "\n");
                linkBuffer.append("name : " + "'" + info.name + "'," + "\n");
                linkBuffer.append("des : " + "'" + info.desc + "'" + "\n");
                linkBuffer.append("}," + "\n");
            }
        }
        linkBuffer.append("]" + "\n");

        return linkBuffer;
    }

    private int isUpStreamNode(String nodeName)
    {
        return upStreamNodes.contains(nodeName) ? 1 : 2;
    }

    private String getSize(String name)
    {
        if (name == null)
        {
            return "[110, 60]";
        }
        else
        {
            String dealName = name.replaceAll("\\s+", " ");
            int height = ((dealName.length() / 16) + 1) * 23;
            return "[110, "+ height + "]";
        }

    }

    private StringBuffer getNodeBuffer()
    {
        StringBuffer nodeBuffer = new StringBuffer();
        nodeBuffer.append("[" + "\n");

        for (int i = 0; i < nodeInfos.size(); i++)
        {
            if (i == 0)
            {
                nodeBuffer.append("{" + "\n");
                NodeInfo info = nodeInfos.get(i);
                nodeBuffer.append("name : " + "'" + info.name + "'," + "\n");
                nodeBuffer.append("des : " + "'" + info.topic + "'," + "\n");
                nodeBuffer.append("symbolSize : " + "[100, 60]" + ",\n");
                nodeBuffer.append("symbol :\"circle\""+ ",\n");
                nodeBuffer.append("category : " + 0 + "\n");
                nodeBuffer.append("}," + "\n");
            }
            else if (i == nodeInfos.size() - 1)
            {
                nodeBuffer.append("{" + "\n");
                NodeInfo info = nodeInfos.get(i);
                nodeBuffer.append("name : " + "'" + info.name + "'," + "\n");
                nodeBuffer.append("des : " + "'" + info.topic + "'," + "\n");
                nodeBuffer.append("symbolSize : " + getSize(info.name) + ",\n");
                nodeBuffer.append("symbol :\"circle\"" + ",\n");
                nodeBuffer.append("category : " + isUpStreamNode(info.name) + "\n");
                nodeBuffer.append("}" + "\n");
            }
            else
            {
                nodeBuffer.append("{" + "\n");
                NodeInfo info = nodeInfos.get(i);
                nodeBuffer.append("name : " + "'" + info.name + "'," + "\n");
                nodeBuffer.append("des : " + "'" + info.topic + "'," + "\n");
                nodeBuffer.append("symbolSize : " + getSize(info.name) + ",\n");

                nodeBuffer.append("symbol :\"circle\"" + ",\n");
                nodeBuffer.append("category : " + isUpStreamNode(info.name) + "\n");
                nodeBuffer.append("}," + "\n");
            }

        }
        nodeBuffer.append("]" + "\n");
        return nodeBuffer;
    }


}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章