JS+Antv G2製做疫情地圖

歷經千辛萬苦,終於把這地圖給作出來了,可是。。。emm,很醜,有不少須要優化的地方,這個地圖一開始一直在antv L7的實例中找,沒有找到,通過查找資料,參考這篇博客才頓悟,原來能夠獲取中國地圖的數據,作一個圖表,如下是個人思路:css

htmlhtml

<div id='map'></div>
複製代碼

css,g2-tooltip和 g2-tooltip-list是官網複製的樣式,是當鼠標滑過是顯示的div的樣式jquery

<style>
    .labelclass {
      width: 50px;
      height: 50px;
      border-radius: 50%;
      color: #9c0a0d;
      text-align: center;
      line-height: 50px;
    }
    .g2-tooltip{
      position: absolute;
        visibility: hidden;
        border: 1px solid #efefef;
        background-color: white;
        color: #000;
        opacity: 0.8;
        padding: 5px 15px;
        transition: top 200ms,left 200ms;
    }
    .g2-tooltip-list{
    margin: 10px;
  }
  </style>
複製代碼

引入須要的js文件ajax

<script src="jquery-3.4.1.min.js"></script>
  <script src="https://gw.alipayobjects.com/os/lib/antv/g2/3.4.10/dist/g2.min.js"></script>
  <script src="https://unpkg.com/@antv/data-set"></script>
複製代碼

爲了不回調地獄混亂思路,我封裝了promise類型的ajaxjson

function $get(url) {
    return new Promise((resolve, rejected) => {
        $.get(url, res => {
            resolve(res)
        })
    })
}
複製代碼

封裝getColor函數,判斷數據的區域獲得不一樣的顏色api

function getColor(v) {
    const trend = ['#ffefd7', '#ffd2a0', '#fe8664', '#e64b47', '#c91014', '#9c0a0d',];
    return v > 9999
        ? trend[5]
        : v > 999
            ? trend[4]
            : v > 499
                ? trend[3]
                : v > 99
                    ? trend[2]
                    : v > 9
                        ? trend[1]
                        : trend[0];
}
複製代碼

先來作地圖的框架數組

let mapData = await $get('https://geo.datav.aliyun.com/areas/bound/100000_full.json')
   
    var chart = new G2.Chart({
        container: 'map',
        height: 1000,
        width: 1000,
        padding: [55, 20]
    });
    chart.scale({
        //sync:當 chart 存在不一樣數據源的 view 時,用於統一相同數據屬性的值域範圍
        //nice:默認爲 true,用於優化數值範圍,使繪製的座標軸刻度線均勻分佈。例如原始數據的範圍爲 [3, 97],若是 nice 爲 true,那麼就會將數值範圍調整爲 [0, 100]
        x: { sync: true, nice: false },
        y: { sync: true, nice: false }
    })
    //chart.coord().reflect('' | 'x' | 'y'): 座標系轉置,將 x 或者 y 的起始、結束值倒置。
    chart.coord().reflect();
    chart.axis(false);

    //處理數據
    var ds = new DataSet();
    // createView建立並返回一個數據視圖實例
    var dv = ds.createView('back')
        .source(mapData, {
            type: 'GeoJSON'
        })
        .transform({
            //geo.projection 地理映射
            type: 'geo.projection',
            projection: 'geoMercator',
            as: ['x', 'y', 'centroidX', 'centroidY']
        });
    //繪製地圖
    var bgView = chart.view();
    bgView.source(dv);
    bgView.polygon()
        .position('x*y')
        .style({
            fill: '#000088',//地圖顏色
            stroke: '#b1b1b1',//界線顏色
            lineWidth: 0.5,//線粗細
            fillOpacity: 1
        })
複製代碼

好了,地圖框架出來了promise

接下來要將疫情數據導出到圖表上,我是從網站上獲得的數據,因此還要進行處理bash

let res = await $get('http://lovebridge.migu.cn:18188/api/map?url=http:%2F%2Fgarnetcdn.migu.cn%2Flovebridge.html')
        res = res.data.country[0].province//處理數據,獲得一個數組
複製代碼

將疫情數據和地圖串聯起來,只能經過地名,可是疫情書籍裏地名沒有顯示市、省,因此我用了find和slice方法,找到對應的對象,處理我須要的數據markdown

//處理疫情數據,顯示數據
    var userData = ds.createView().source(res)
    userData.transform({
        //數據轉換,type至關於數組轉換的方法
        type: 'map',
        //因爲我從網上得到的數據中市省都去掉了,因此我經過查找匹配前兩個字符同樣的獲得經緯度
        callback: function (obj, index) {
            let one = dv.rows.find(item => { return item.name.slice(0, 2) === obj.na.slice(0, 2) })
            obj.x = one.centroidX * 1;
            obj.y = one.centroidY * 1;
            obj.data = parseInt(obj.tn.split(',')[0])
            one.data = obj.data
            return obj;
        }
    });
    //以下是數據顯示及樣式
    var pointView = chart.view();
    pointView.source(userData);
    pointView.intervalStack()
        .position('x*y').label('na', {
            offset: -5,
            textStyle: {
                fontSize: 10,
                fill: '#000',
            },
            formatter: (text, item) => {
                const d = item.point;
                return d.na + '\n' + d.data;
            }
        })
複製代碼

須要按確診人數的數量來讓不一樣區域顯示相應的顏色,我前面已經將數據存在userData上了

bgView.polygon().position('x*y').color('data', getColor)//傳入回調函數,使不一樣的數據顯示不同的背景顏色
複製代碼

當鼠標劃過期,顯示相應的數據,只有chart有tooltip方法

chart.tooltip({
        showTitle: false, // 默認標題不顯示
        containerTpl:
            `<div class="g2-tooltip"><ul class="g2-tooltip-list"></ul>
      </div>`,
        itemTpl: '<li >確診{value}例</li>'
    })
複製代碼

取消動畫,將圖表渲染至畫布

chart.animate(false)
chart.render();
複製代碼

成品

下面是總的js代碼

function $get(url) {
    return new Promise((resolve, rejected) => {
        $.get(url, res => {
            resolve(res)
        })
    })
}
function getColor(v) {
    const trend = ['#ffefd7', '#ffd2a0', '#fe8664', '#e64b47', '#c91014', '#9c0a0d',];
    return v > 9999
        ? trend[5]
        : v > 999
            ? trend[4]
            : v > 499
                ? trend[3]
                : v > 99
                    ? trend[2]
                    : v > 9
                        ? trend[1]
                        : trend[0];
}
async function aa() {
    let mapData = await $get('https://geo.datav.aliyun.com/areas/bound/100000_full.json')
   
    var chart = new G2.Chart({
        container: 'map',
        // forceFit: true,
        height: 1000,
        width: 1000,
        padding: [55, 20]
    });
    // // force sync scales
    chart.scale({
        //sync:當 chart 存在不一樣數據源的 view 時,用於統一相同數據屬性的值域範圍
        //nice:默認爲 true,用於優化數值範圍,使繪製的座標軸刻度線均勻分佈。例如原始數據的範圍爲 [3, 97],若是 nice 爲 true,那麼就會將數值範圍調整爲 [0, 100]
        x: { sync: true, nice: false },
        y: { sync: true, nice: false }
    })
    //chart.coord().reflect('' | 'x' | 'y'): 座標系轉置,將 x 或者 y 的起始、結束值倒置。
    chart.coord().reflect();
    chart.axis(false);

    //處理數據,繪製地圖
    var ds = new DataSet();
    // createView建立並返回一個數據視圖實例
    var dv = ds.createView('back')
        .source(mapData, {
            type: 'GeoJSON'
        })
        .transform({
            //geo.projection 地理映射
            type: 'geo.projection',
            projection: 'geoMercator',
            as: ['x', 'y', 'centroidX', 'centroidY']
        });

    var bgView = chart.view();
    bgView.source(dv);
    bgView.polygon()
        .position('x*y')
        .style({
            fill: '#000088',//地圖顏色
            stroke: '#b1b1b1',//界線顏色
            lineWidth: 0.5,//線粗細
            fillOpacity: 1
        })
        .color('data', getColor)//傳入回調函數,使不一樣的數據顯示不同的背景顏色

        let res = await $get('http://lovebridge.migu.cn:18188/api/map?url=http:%2F%2Fgarnetcdn.migu.cn%2Flovebridge.html')
        res = res.data.country[0].province//處理數據,獲得一個數組
    //處理疫情數據,顯示數據
    var userData = ds.createView().source(res)
    userData.transform({
        //數據轉換,type至關於數組轉換的方法
        type: 'map',
        //因爲我從網上得到的數據中市省都去掉了,因此我經過查找匹配前兩個字符同樣的獲得經緯度
        callback: function (obj, index) {
            let one = dv.rows.find(item => { return item.name.slice(0, 2) === obj.na.slice(0, 2) })
            obj.x = one.centroidX * 1;
            obj.y = one.centroidY * 1;
            obj.data = parseInt(obj.tn.split(',')[0])
            one.data = obj.data
            return obj;
        }
    });
    //以下是數據顯示及樣式
    var pointView = chart.view();
    pointView.source(userData);
    pointView.intervalStack()
        .position('x*y').label('na', {
            offset: -5,
            textStyle: {
                fontSize: 10,
                fill: '#000',
            },
            formatter: (text, item) => {
                const d = item.point;
                return d.na + '\n' + d.data;
            }
        })


    //圖例顯示在右邊
    chart.legend('data', {
        position: 'right',
    })

    //當鼠標劃過期,顯示相應的數據,只有chart有tooltip方法
    chart.tooltip({
        showTitle: false, // 默認標題不顯示
        containerTpl:
            `<div class="g2-tooltip"><ul class="g2-tooltip-list"></ul>
      </div>`,
        itemTpl: '<li >確診{value}例</li>'
    })
    chart.animate(false)
    chart.render();
}
aa()
複製代碼
相關文章
相關標籤/搜索