概述

在前文中,有一篇文章讲述了Openlayers2结合Echart实现地图统计图,还以一篇文章讲述了结合heatmap.js实现Openlayers中热力图的展示。在本文,书接前文,讲述Openlayers如何结合Echart实现热力图。


效果


全图效果


放大效果

实现

1、关键点

echart实现heatmap的关键点在与屏幕坐标,所以,在地图中,应通过地理坐标到屏幕坐标的转换函数,将地理坐标转换为屏幕坐标。


2、实现代码

我将热力图扩展成为了一个openlayers的layer扩展,实现代码如下:

OpenLayers.Layer.EchartHeatmap = OpenLayers.Class(OpenLayers.Layer,
    {
        isBaseLayer : false,
        heatmap : null,
        mapLayer : null,
        heatdata : [],
        initialize : function (name, map, options)
        {
            var scope = this, heatdiv = document.createElement("div"), handler;
            
            OpenLayers.Layer.prototype.initialize.apply(this, [name, options]);
            
            heatdiv.style.cssText = "position:absolute;width:" + map.size.w + "px;height:" 
                + map.size.h + "px;";
            this.div.appendChild(heatdiv);
            this.map = map;
            this.heatdiv = heatdiv;
            this.heatdata = options.heatdata;
            this.opacity = options.opacity;
            handler = function (e)
            {
                if (scope.heatdata.length > 0)
                {
                    scope.updateLayer(e);
                }
            };
            handler();
            map.events.register("zoomend", this, handler);
            map.events.register("moveend", this, handler);
        },
        updateLayer : function (e)
        {
            var scope = this;
            require(
                [
                    'echarts',
                    'echarts/chart/heatmap'
                ],
                function (ec)
            {
                var myChart = ec.init(scope.heatdiv);
                var heatD = [];
                var data = scope.heatdata;
                var orgXy, w, h;
                if(e){
                    orgXy = e.object.layerContainerOriginPx;

                }
                else{
                    orgXy={x:0,y:0};
                }
                w = scope.map.size.w;
                h = scope.map.size.h;
                scope.heatdiv.style.cssText = "position:absolute;top:"+(-orgXy.y)+"px;left:"+(-orgXy.x)+
                    "px;width:" + w + "px;height:" + h + "px;";
                for (var i = 0; i < data.length; ++i)
                {
                    var d = data[i];
                    var scrPt = scope.map.getPixelFromLonLat(new OpenLayers.LonLat(d.lon, d.lat));
                    var x = scrPt.x,
                        y = scrPt.y;
                    heatD.push([
                        x,
                        y,
                        d.count
                    ]);
                }
                var option =
                {
                    series : [
                        {
                            type : 'heatmap',
                            data : heatD,
                            opacity:scope.opacity,
                            gradientColors : [
                                {
                                    offset : 0.4,
                                    color : 'green'
                                },
                                {
                                    offset : 0.5,
                                    color : 'yellow'
                                },
                                {
                                    offset : 0.8,
                                    color : 'orange'
                                },
                                {
                                    offset : 1,
                                    color : 'red'
                                }
                            ],
                            minAlpha : 0.2,
                            valueScale : 2
                        }
                    ]
                };
                myChart.setOption(option);
            });
        },
        destroy : function ()
        {
            OpenLayers.Layer.Grid.prototype.destroy.apply(this, arguments);
        },
        CLASS_NAME : "OpenLayers.Layer.EchartHeatmap"
    }
);
前台调用的代码如下:

<html>
<head>
	<meta charset="UTF-8">
	<title>heatmap.js OpenLayers Heatmap Layer</title>
	<link rel="stylesheet" href="../../../plugin/OpenLayers-2.13.1/theme/default/style.css" type="text/css">
	<style>
		html, body, #map,#chart{
			padding:0;
			margin:0;
			height:100%;
			width:100%;
			overflow: hidden;
		}
		#chart{
			position: absolute;
			top: 0px;
			left: 0px;
			z-index: 900;
		}
	</style>
	<script src="../../../plugin/OpenLayers-2.13.1/OpenLayers.js"></script>
	<script src="../../../plugin/jquery/jquery-1.8.3.js"></script>
	<script src="../../../plugin/echart/build/dist/echarts.js"></script>
	<script src="extend/echartheatlayer.js"></script>
	<script type="text/javascript">
		require.config({
	        paths: {
	            echarts: '../../../plugin/echart/build/dist'
	        }
	    });
		var map;
		function init(){			
			var format = 'image/png';
			var bounds = new OpenLayers.Bounds(
					73.45100463562233, 18.16324718764174,
					134.97679764650596, 53.531943152223576
			);
			var options = {
				controls: [],
				maxExtent: bounds,
				maxResolution: 0.2403351289487642,
				projection: "EPSG:4326",
				units: 'degrees'
			};
			map = new OpenLayers.Map('map', options);
			var wms1 = new OpenLayers.Layer.WMS("base_map",
					"http://localhost:8088/geoserver/lzugis/wms",
					{
						layers: "province",
						transparent: true
					}, {
						isBaseLayer: true,
						singleTile: true
					});
			map.addControl(new OpenLayers.Control.Zoom());
			map.addControl(new OpenLayers.Control.Navigation());
			var heatmap = new OpenLayers.Layer.EchartHeatmap("heatmap",map,{
				heatdata:data,
				opacity:0.8
			});
			var wms2 = new OpenLayers.Layer.WMS("base_map",
					"http://localhost:8088/geoserver/lzugis/wms",
					{
						layers: "county",
						transparent: true
					}, {
						isBaseLayer: false,
						singleTile: true,
						opacity:0.2
					});
			map.addLayers([wms1,heatmap,wms2]);
			map.zoomToExtent(bounds);
		}
	</script>
</head>
<body onload="init()">
<div id="map">
</div>
</body>
</html>
其中,变量data的数据格式如下:

[
  {name:"东方市",lon:108.633357,lat:19.097025,count:30},
  {name:"临高县",lon:109.686515,lat:19.91785,count:47},
  {name:"儋州市",lon:109.575851,lat:19.518256,count:43},
  {name:"昌江黎族自治县",lon:109.048657,lat:19.258351,count:71},
  {name:"白沙黎族自治县",lon:109.448097,lat:19.235657,count:70},
  ……
]


查看示例


传播GIS知识 | 交流GIS经验 | 分享GIS价值 | 专注GIS发展

技术博客

http://blog.csdn.net/gisshixisheng

在线教程

http://edu.csdn.net/course/detail/799
Github

https://github.com/lzugis/

联系方式

q       q:1004740957

e-mail:niujp08@qq.com

公众号:lzugis15

Q Q 群:452117357(webgis)
             337469080(Android)






posted on 2016-07-25 07:52  LZU-GIS  阅读(938)  评论(0编辑  收藏  举报