JS+Antv G2制作疫情地图

历经千辛万苦,终于把这地图给做出来了,但是。。。emm,很丑,有很多需要优化的地方,这个地图一开始一直在antv L7的实例中找,没有找到,经过查找资料,参考这篇博客才顿悟,原来可以获取中国地图的数据,做一个图表,以下是我的思路:

html

css,g2-tooltip和 g2-tooltip-list是官网复制的样式,是当鼠标滑过是显示的div的样式


引入需要的js文件


  
  

为了避免回调地狱混乱思路,我封装了promise类型的ajax

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

封装getColor函数,判断数据的区域得到不同的颜色

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
        })

好了,地图框架出来了

image

接下来要将疫情数据导出到图表上,我是从网站上得到的数据,所以还要进行处理

  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方法,找到对应的对象,处理我需要的数据

//处理疫情数据,显示数据
    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:
            `
    `, itemTpl: '
  • 确诊{value}例
  • ' })

    取消动画,将图表渲染至画布

     chart.animate(false)
    chart.render();
    

    成品

    image

    下面是总的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:
                `
      `, itemTpl: '
    • 确诊{value}例
    • ' }) chart.animate(false) chart.render(); } aa()

      你可能感兴趣的:(JS+Antv G2制作疫情地图)