使用ECharts繪製網址徑向樹狀圖

AnRFDev發表於2021-09-02

an.rustfisher.com有很多內容,很多頁面。如果用一個樹狀圖把所有頁面展示出來會是什麼效果?
第一時間想到了ECharts

最後效果: https://an.rustfisher.com/an-tree.html

資料處理

資料來源於配置檔案。我們只需要把內容讀出來,整理成ECharts需要的格式並儲存為檔案。

yml

Android站用的框架是Mkdocs,網址都設定在mkdocs.yml裡。關鍵配置如下

nav:
  - Android basic:
    - 開始:
      - 新建工程: android/startProject/start_new_project.md
      - 使用Kotlin: android/startProject/as-use-kotlin.md
    - Activity:
      - Activity綜述: android/activity/overview.md

我們需要把這些資料讀出來,弄成ECharts可以用的格式。

開啟PyCharm,用python來處理資料。

python處理資料

我們使用3.7版本python。要讀取yml的內容,不想用讀文字的方式一行行來讀,還得自己解析。
python中有個庫PyYAML專門用於讀取yml格式的資料。

在PyCharms裡裝上這個包。用它來讀取yml裡的資料。

import yaml

    with open(md_file, encoding='utf8') as a_yaml_file:
        # 解析yaml
        yaml_data = yaml.load(a_yaml_file, Loader=yaml.FullLoader)
        nav = yaml_data['nav']

ECharts需要的格式是namechildren。同時可以新增別的欄位。

{
  "name": "Android教程",
  "children": [
    {
      "name": "Android basic",
      "children": []
    }]
}

讀取到的資料層級比較多,用遞迴方法來處理它們。把所有的資料都遍歷一遍,整理成需要的格式。

遞迴的時候,遇到陣列,則繼續遞迴;遇到字串,則表示可以拼接網址了。

完整指令碼如下

import json
import os
import yaml


def gen_url_map(main_site, md_file):
    with open(md_file, encoding='utf8') as a_yaml_file:
        # 解析yaml
        yaml_data = yaml.load(a_yaml_file, Loader=yaml.FullLoader)

        nav = yaml_data['nav']

        sorted_data = {"name": "Android教程", "children": [], "collapsed": False}

        for big_dict in nav:
            load_url(main_site, big_dict, sorted_data)

        url_file = 'android-url-map.json'
        if os.path.exists(url_file):
            os.remove(url_file)
        with open(url_file, 'w') as s:
            s.write(str(json.dumps(sorted_data, ensure_ascii=False)))


def load_url(main_site, input_dict, res_data):
    """
    遞迴處理資料
    """
    for k1 in input_dict:
        v1 = input_dict[k1]
        if isinstance(v1, list):
            item1 = {"name": k1, "children": []}
            res_data['children'].append(item1)
            for v1_child in v1:
                load_url(main_site, v1_child, item1)
        elif isinstance(v1, str):
            # 此時已經是url了
            final_item = {"name": k1, "url": main_site + v1[0:-3]}
            res_data['children'].append(final_item)
            return final_item


if __name__ == '__main__':
    print("生成android站的sitemap")
    gen_url_map('https://www.an.rustfisher.com/',
                '/Users/rustfisher/mkdocs.yml')

最後寫一個android-url-map.json檔案。

製作網頁

經過觀察,我們選用徑向樹狀圖(tree-radial)。
檢視ECharts的徑向樹狀圖使用示例,下載一個示例html,在它的基礎上修改。

新增上jquery的引用。

<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>

修改要讀取的json檔名

$.getJSON('./android-url-map.json', function (data) { /* ... */ }

把前面得到的json檔案和這個html檔案放在同一層級,上傳伺服器。

開啟: https://an.rustfisher.com/an-tree.html 可以看到效果。

擴大顯示範圍

這個時候的網頁體驗不是很好,頁面不夠大,圖表超出上下範圍了。可以給它添個豎直的滾動條overflow-y: scroll

<html style="height: 100%; width: 100%; overflow-y: scroll;">

修改一下網頁的body。外層的container佔100%寬高,裡面的chartContainer給一個min-height: 1600px

<body style="height: 100%; margin: 0; width: 100%;">
    <div id="container" style="height: 100%; width: 100%;">
        <div id="chartContainer" style="width: 100%; min-height: 1600px"></div>
    </div>

script里加上對resize的監聽

$(window).on('resize', function () {
    if (myChart != null && myChart != undefined) {
        myChart.resize();
    }
});

這時再看瀏覽器的效果,圖表有了更多的空間顯示。

參考

點選開啟頁面

預設點選效果是摺疊和展開。對於最末尾的葉子節點,加一個點選事件讓它開啟相應的介面。

myChart.on('click', function (params) {
    if (params.data && params.data.url) {
        window.open(params.data.url);
    }
});

最後效果: https://an.rustfisher.com/an-tree.html

相關文章