Echart - 地图散点图(服务网点图)的实现

 

Echart是百度开发的一个javascript图表库,可以流程运行于pc和移动端,底层依赖轻量级的 Canvas 类库 ZRender
ECharts 提供了常规的折线图,柱状图,散点图,饼图,K线图,用于统计的盒形图,用于地理数据可视化的地图,热力图,线图,用于关系数据可视化的关系图,treemap,多维数据可视化的平行坐标,还有用于 BI 的漏斗图,仪表盘,并且支持图与图之间的混搭。
支持:
多个坐标系:直角坐标系,极坐标系,地理坐标系;
移动端的优化:可以按需打包,支持移动端手指缩放;
数据的深度交互;
大量数据的展现:基于微博签到的100K条数据展现;
多维数据以及丰富的视觉效果;
动态数据和绚丽特效;
上手Echart(官网案例):
国际惯例,引入js文件,这里还是要先引入jquery。
<!DOCTYPE html>
<html>
<header>
    <meta charset="utf-8">
    <!-- 引入 ECharts 文件 -->
    <script src="echarts.min.js"></script>
</header>
</html>

准备一个容器作为画布:

<body>
    <!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
    <div id="main" style="width: 600px;height:400px;"></div>
</body>

写js代码(这里的部分写法与highchart的写法很类似,以至于我曾经一直在highchart的api里面找echart的效果...):

<script type="text/javascript">
        // 基于准备好的dom,初始化echarts实例
        var myChart = echarts.init(document.getElementById('main'));
        // 指定图表的配置项和数据
        var option = {
            //标题
            title: {
                text: 'ECharts 入门示例'
            },
            tooltip: {},
            //图例
            legend: {
                data:['销量']
            },
            //横坐标
            xAxis: {
                data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
            },
            //纵坐标
            yAxis: {},
            //数据列
            series: [{
                name: '销量',
                type: 'bar',
                data: [5, 20, 36, 10, 10, 20]
            }]
        };
        // 使用刚指定的配置项和数据显示图表。
        myChart.setOption(option);
    </script>

下面还是通过自己的一个例子来简单说明一下:写法可能不止一种。

数据是之前通过jsoup解析中通网页,将地址存到数据库里,然后根据地址查询百度地图api,获得经纬度信息再update到数据库里。(过程这里贴不下,以后整理一下再贴出来)

数据获取.......

List<Loc2> dat = testChartService.selectLoc();
        Map all=new HashMap();
        for(Loc2 loc2:dat){
            List list = new ArrayList();
            list.add(loc2.getLongitude());
            list.add(loc2.getLatitude());
            all.put(loc2.getAddress(),list);
        }
        System.out.println(all.toString());
        writeJson(response, all);

// 以json格式输出
    public void writeJson(HttpServletResponse response, Object obj) {
        PrintWriter writer = null;
        try {
            response.setContentType("application/json" + ";charset=utf-8");
            writer = response.getWriter();

            Object jsonObject = null;
            if (obj instanceof List) {
                jsonObject = JSONArray.toJSON(obj);
            } else {
                jsonObject = JSONObject.toJSON(obj);
            }
            writer.print(jsonObject.toString());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }

 

//这是数据格式:
loc:{
白玉路346号=[121.423744, 31.23829], 
新民路城南工商所对面巷子( 南苑菜市旁边 )=[106.577573, 31.082472], 
长江路26号,苏展工业坊b栋1层=[118.328064, 33.949859]
}
//数据是之前做的,此处只是给个例子,可参考例子,写自己的地址和经纬度。
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>散点图</title>
    <!-- 先引入jquery,再引入echart -->
    <script src="../js/jquery-2.1.4.min.js"></script>
    <script src="../js/bootstrap.js"></script>
    <script src="../js/echart/echarts.min.js"></script>
    <script type="text/javascript">
        $(function () {
            //通过ajax请求来获取后台数据
            $.ajax({
                type: 'post',
                //bashPath是jsp里面,获取的项目路径
                url: '<%=basePath%>loc',
                async: true,
                cache: false,
                dataType: 'json',
                success: function (data) {
                    //把数据转化一下
                    data=eval(data);
                    //res是数据,要传到api里面的
                    var res = [];
                    //官方案例中,每个点还有一个value值,这里不需要,所以要改造一下。这里参考案例生成的数据格式,自己重新封装了一下
                    for(var key in data)
                    {
                        console.log(key+"");
                        res.push({
                            name: key+"",
                            value: data[key].concat(1)   //这里concat后面的值就是value,这里统一设置成1。
                        });
                    }
                    //这里需要下载中国地图的json文件,因为要创建地图需要初始化地图,至于怎么初始化的,json里面的数据也看不懂。
                    $.get('../js/echart/china.json', function (chinaJson) {
                        echarts.registerMap('china', chinaJson);  //注册地图名
                        var chart = echarts.init(document.getElementById('main'));   //这里是主体的初始化echart方法,与上面的简单demo类似。
                        chart.setOption({
                            backgroundColor: '#404a59',
                            title: {
                                text: '中通快递全国网点分布',
                                subtext: 'data from 中通快递',
                                sublink: 'http://www.zto.com/',
                                x: 'center',
                                textStyle: {
                                    color: '#fff'
                                }
                            },
                            legend: {
                                orient: 'vertical',
                                y: 'bottom',
                                x: 'right',
                                data: ['服务网点'],
                                textStyle: {
                                    color: '#fff'
                                }
                            },
                            //地图坐标系必备的配置,具体的含义可以参考api,索性都是中文的,没有什么阅读障碍。
                            geo: {
                                silent:false,
                                map: 'china',
                                label: {
                                    emphasis: {
                                        show: false
                                    }
                                },
                                itemStyle: {
                                    hoverAnimation:false,
                                    normal: {
                                        areaColor: '#323c48',
                                        borderColor: '#000'
                                    },
                                    emphasis: {
                                        areaColor: '#2a333d',
                                        opacity:0
                                    }
                                }
                            },
                            series: [
                                {
                                    name: '服务网点',
                                    type: 'scatter',
                                    coordinateSystem: 'geo',    //参照系:之前设置的geo。
                                    //这里是api数据接受的的地方
                                    data:res,
                                    symbolSize: 3,    //散点半径
                                    label: {
                                        normal: {
                                            show: false
                                        },
                                        emphasis: {
                                            show: false
                                        }
                                    },
                                    hoverAnimation:false,
                                    silent:false,
                                    animation:false,
                                    z:3
                                }
                            ]
                        });
                    });
                }
            });
        });
    </script>
</head>
<body>
<!--  长宽必须指定,否则可能无法显示图像 -->
<div id="main" class="main" style="width: 1000px;height:800px;">
</div>
</body>
</html>
echart内部是高度封装的了,配置起来非常简单,地图这样看起来很复杂的东西配置也不是很困难。
遇到过一个小问题,就是底图和数据点都有鼠标hover效果,导致图上常常闪烁有时是地图的hover有时是点的hover,尤其是比较密集的地区。
后来通过opacity 属性为0,使hover不显示任何特效解决。(其实我配置了许多的内容,包括禁用鼠标事件/禁用动画/设置z值等,不知道具体是哪个生效了,但是问题确实解决了。)
 

本案例参考了官网中的散点图案例,但是去掉了许多内容,图没有美化过,只是作为一个demo案例而已。

附上官网例子,对比看看api接受的是什么格式的数据,我们就拼什么格式的数据。

var geoCoordMap = {
    "海门":[121.15,31.89],
    "鄂尔多斯":[109.781327,39.608266],
    "招远":[120.38,37.35],
    "舟山":[122.207216,29.985295],
    "齐齐哈尔":[123.97,47.33],
    "盐城":[120.13,33.38],
    "赤峰":[118.87,42.28],
    "青岛":[120.33,36.07],
    "乳山":[121.52,36.89],
    "金昌":[102.188043,38.520089],
    "泉州":[118.58,24.93],
    "莱西":[120.53,36.86],
    "日照":[119.46,35.42],
    "胶南":[119.97,35.88],
    "南通":[121.05,32.08],
    "拉萨":[91.11,29.97]
};
//这里是生成series的数据,将经纬度和value值映射起来,我根据这个方法,最后自己写了一个方法,生成同样格式的数据,实现了对value的屏蔽。
var convertData = function (data) {
    var res = [];
    for (var i = 0; i < data.length; i++) {
        var geoCoord = geoCoordMap[data[i].name];
        if (geoCoord) {
            res.push({
                name: data[i].name,
                value: geoCoord.concat(data[i].value)
            });
        }
    }
    return res;
};
option = {
    backgroundColor: '#404a59',
    title: {
        text: '全国主要城市空气质量',
        subtext: 'data from PM25.in',
        sublink: 'http://www.pm25.in',
        x:'center',
        textStyle: {
            color: '#fff'
        }
    },
    tooltip: {
        trigger: 'item',
        formatter: function (params) {
            return params.name + ' : ' + params.value[2];
        }
    },
    legend: {
        orient: 'vertical',
        y: 'bottom',
        x:'right',
        data:['pm2.5'],
        textStyle: {
            color: '#fff'
        }
    },
    visualMap: {
        min: 0,
        max: 200,
        calculable: true,
        inRange: {
            color: ['#50a3ba', '#eac736', '#d94e5d']
        },
        textStyle: {
            color: '#fff'
        }
    },
    geo: {
        map: 'china',
        label: {
            emphasis: {
                show: false
            }
        },
        itemStyle: {
            normal: {
                areaColor: '#323c48',
                borderColor: '#111'
            },
            emphasis: {
                areaColor: '#2a333d'
            }
        }
    },
    series: [
        {
            name: 'pm2.5',
            type: 'scatter',
            coordinateSystem: 'geo',
            data: convertData([
                {name: "海门", value: 9},
                {name: "鄂尔多斯", value: 12},
                {name: "招远", value: 12},
                {name: "舟山", value: 12},
                {name: "齐齐哈尔", value: 14},
                {name: "盐城", value: 15},
                {name: "赤峰", value: 16},
                {name: "青岛", value: 18},
                {name: "乳山", value: 18},
                {name: "金昌", value: 19},
                {name: "泉州", value: 21},
                {name: "莱西", value: 21},
                {name: "日照", value: 21},
                {name: "胶南", value: 22},
                {name: "南通", value: 23},
                {name: "拉萨", value: 24}
            ]),
            symbolSize: 12,
            label: {
                normal: {
                    show: false
                },
                emphasis: {
                    show: false
                }
            },
            itemStyle: {
                emphasis: {
                    borderColor: '#fff',
                    borderWidth: 1
                }
            }
        }
    ]
}

 

参考资料:

 

 

posted @ 2016-07-31 12:32  open_sesame  Views(19341)  Comments(6Edit  收藏  举报