多种方法实现热力图(百度API、ArcGIS API、leaflet API 和 QGIS、Kepler.gl

# 原理

    热力图原理:为离散点信息创建一个Mask。Mask是一个圆形区域,半径为该点可以对最终热力图像产生影响的区域半径。中心点的权重为1,越向边缘辐射,权重越低,边缘部分的权重为0。Mask的渐变过程可以考虑多种形式,如线性变化,二次曲线等。将所有离散点Mask进行叠加,产生一幅灰度图像。相邻Mask的重叠部分进行权重累加操作,最终灰度图中每个像素点的数值大小就是所有和其有关的Mask中的权重之和。 离散点密度越高的地方,灰度图种像素点数值越高,即图像越亮。根据具体项目不同,可考虑将权重乘上一个固定系数。将生成的灰度图映射到彩色图像上。

# 数据

    实现将收集的POI数据进行热力图可视化   

    数据:北京市旅游景点.xls

      导入至mysql数据库

    本文实现了由JavaScript API 和 非代码形式生成热力图的方法。 

#1# 百度地图JavaScript API

    百度地图热力图API:地图JS API示例 | 百度地图开放平台

<%@ page language="java" contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
   <meta charset="UTF-8">
   <title>热力图</title>
   <style type="text/css">
html {
	height: 100%
}

body {
	height: 100%;
	margin: 0px;
	padding: 0px
}

#map {
	height: 100%
}
   </style>

<script type="text/javascript"  src="//api.map.baidu.com/api?v=2.0&ak=密钥"></script>
<script type="text/javascript"  src="//api.map.baidu.com/library/Heatmap/2.0/src/Heatmap_min.js"></script>

</head>
<body>
	<div id="map"></div>

	<%@ page import="java.sql.*"%>
	<%@ page import="java.io.PrintWriter"%>
	<%
		request.setCharacterEncoding("utf-8");
		Connection con;
		Statement stmt = null;
		ResultSet rs;
		String all = "";

		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			System.out.println("数据库连线成功");
		} catch (Exception e) {
			System.out.println("数据库连线失败");
		}
		try {
			String url = "jdbc:mysql://127.0.0.1:3306/scenery?serverTimezone=UTC";
			String user = "root";
			String password = "123456";
			con = DriverManager.getConnection(url, user, password);
			stmt = con.createStatement();
			System.out.println("成功连接到本地数据库");
		} catch (Exception e) {
			System.out.println("本地数据库连接失败");
		}

		try {
			rs = stmt.executeQuery("select * from ScenerySpot");
			while (rs.next()) {
				double lat = rs.getDouble("Latitude");
				double lng = rs.getDouble("Longitude");
				String s = lng + "," + lat + ";";
				all = all + s;
			}
		} catch (Exception e) {
			System.out.println("数据获取失败");
			System.out.println(e);
		}
	%>

</body>

<script>
    var d = '<%=all%>'
	var poi = d.split(';');//解析字符串
	var pointList = new Array();
	for (var i = 0; i < poi.length; i++) {
		var points = poi[i].split(',');
		var data = {};
		data.lng = points[0];
		data.lat = points[1];
		data.count = 20;
		pointList.push(data);
	}

	//判断浏览区是否支持canvas
	function isSupportCanvas() {
		var elem = document.createElement('canvas');
		return !!(elem.getContext && elem.getContext('2d'));
	}
	//alert(isSupportCanvas())

	var map = new BMap.Map("map");
	var point = new BMap.Point(116.418261, 39.921984);
	map.centerAndZoom(point, 10); // 初始化地图,设置中心点坐标和地图级别
	map.enableScrollWheelZoom(); // 允许滚轮缩放
	
	var heatmapOverlay = new BMapLib.HeatmapOverlay({
		"radius" : 20
	});

	map.addOverlay(heatmapOverlay);

	heatmapOverlay.setDataSet({
		data : pointList,
		max : 100
	});
</script>
</html>

#2# ArcGIS API for JavaScript

【4.14版本热力图实现】
https://developers.arcgis.com/javascript/latest/sample-code/visualization-heatmap/index.html

【3.x版本热力图实现】
https://developers.arcgis.com/javascript/3/jssamples/renderer_heatmap.html

【featureLayer】
https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />

    <title>Visualize points with a heatmap - 4.14</title>

    <link rel="stylesheet" href="https://js.arcgis.com/4.14/esri/themes/light/main.css" />

    <style>
        html,
        body,
        #viewDiv {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
        }
    </style>

    <script src="https://js.arcgis.com/4.14/"></script>

    <script>
        require([
            "esri/Map",
            "esri/layers/CSVLayer",
            "esri/views/MapView",
            "esri/layers/TileLayer"
        ], function (Map, CSVLayer, MapView, TileLayer) {
            var url =
                "https://xxxxxxxx/mmm.csv";
            
            var renderer = {
                type: "heatmap",
                colorStops: [
                    { color: "rgba(63, 40, 102, 0)", ratio: 0 },
                    { color: "#472b77", ratio: 0.083 },
                    { color: "#4e2d87", ratio: 0.166 },
                    { color: "#563098", ratio: 0.249 },
                    { color: "#5d32a8", ratio: 0.332 },
                    { color: "#6735be", ratio: 0.415 },
                    { color: "#7139d4", ratio: 0.498 },
                    { color: "#7b3ce9", ratio: 0.581 },
                    { color: "#853fff", ratio: 0.664 },
                    { color: "#a46fbf", ratio: 0.747 },
                    { color: "#c29f80", ratio: 0.83 },
                    { color: "#e0cf40", ratio: 0.913 },
                    { color: "#ffff00", ratio: 1 }
                ],
                maxPixelIntensity: 25,
                minPixelIntensity: 0
            };

            var layer = new CSVLayer({
                url: url,
                renderer: renderer
            });
            
            var baselayer = new TileLayer({
                url: "https://map.geoq.cn/arcgis/rest/services/ChinaOnlineCommunity/MapServer"
            });

            var map = new Map({
                layers: [baselayer]
            });
            map.layers.add(layer)

            var view = new MapView({
                container: "viewDiv",
                center: [116.418261, 39.921984],
                zoom: 10,
                map: map
            });

        });
    </script>
</head>

<body>
    <div id="viewDiv"></div>
</body>

</html>

#3# leaflet

    入门基础:leaflet:入门基础(一)_Dawn_www的博客-CSDN博客_leaflet

    需要的文件:heatmap.js      leaflet-heatmap.js     leaflet.js     leaflet.css

    heatmap文件下载地址:heatmap.js Download

    文件分别在:build文件夹下的heatmap.js       plugins > leaflet-heatmap文件夹下的leaflet-heatmap.js

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>leaflet热力图</title>

<style>
#mapid {
	height: 600px;
}
</style>

<link rel="stylesheet"
	href="https://unpkg.com/leaflet@1.4.0/dist/leaflet.css" />

<script src="https://unpkg.com/leaflet@1.4.0/dist/leaflet.js"></script>
<script src="./heatmap.js"></script>
<script src="./leaflet-heatmap.js"></script>
</head>
<body>
	<div id="mapid"></div>

	<%@ page import="java.sql.*"%>
	<%@ page import="java.io.PrintWriter"%>

	<%
		request.setCharacterEncoding("utf-8");
		Connection con;
		Statement stmt = null;
		ResultSet rs;
		String all = "";

		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			System.out.println("数据库连线成功");
		} catch (Exception e) {
			System.out.println("数据库连线失败");
		}
		try {
			String url = "jdbc:mysql://127.0.0.1:3306/scenery?serverTimezone=UTC";
			String user = "root";
			String password = "123456";
			con = DriverManager.getConnection(url, user, password);
			stmt = con.createStatement();
			System.out.println("成功连接到本地数据库");
		} catch (Exception e) {
			System.out.println("本地数据库连接失败");
		}

		try {
			rs = stmt.executeQuery("select * from ScenerySpot");
			while (rs.next()) {
				double lat = rs.getDouble("Latitude");
				double lng = rs.getDouble("Longitude");
				String s = lng + "," + lat + ";";
				all = all + s;
			}
		} catch (Exception e) {
			System.out.println("数据获取失败");
			System.out.println(e);
		}
	%>

</body>

<script>
    var d = '<%=all%>'
	var poi = d.split(';');//解析字符串
	
 	var arraySpot = new Array();	 		//构建json数组中的对象		
	
	for (var i = 0; i < poi.length; i++) {
		var points = poi[i].split(',');
		var data = {};
		data.lng = parseFloat(points[0]);
		data.lat = parseFloat(points[1]);
		data.count = 1;
		arraySpot.push(data);
	}
 	
/* 	var k =JSON.stringify(arraySpot);
	alert(k); */
 
    var ks = [{ "lat": 39.998547, "lng":116.274853, "count": 1},
        { "lat": 39.886376, "lng": 116.417115, "count": 1 },
        { "lat": 40.364396, "lng": 116.014538, "count": 1 },
        { "lat": 40.420718, "lng": 116.473875, "count": 1 },
        { "lat": 40.29995, "lng": 116.234183, "count": 1 },
        { "lat": 39.924091, "lng": 116.403414, "count": 1 },
        { "lat": 40.02523, "lng": 116.396797, "count": 1 },
    ];
    
  
	//数据
	var testData = {
		max : 20, 
		data : ks // arraySpot
	};  

	//配置
	var cfg = {
		"radius" : 0.1,
		"maxOpacity" : .2, //设置最大的不透明度
		"scaleRadius" : true, //设置热力点是否平滑过渡
		"useLocalExtrema" : true,//使用局部极值
		latField : 'lat',
		lngField : 'lng',
		valueField : 'count'
	};

	var heatmapLayer = new HeatmapOverlay(cfg);

	//图层
	var baseLayer = L.tileLayer(
			'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
				attribution : '...',
				maxZoom : 18
			});

	var map = new L.Map('mapid', {
		center : new L.LatLng(39.56, 116.20),
		zoom : 9,
		layers : [ baseLayer,heatmapLayer ]
	});

	heatmapLayer.setData(testData);
	
</script>
</html>

    这里遇到一个问题:读取数据库数据并按格式组织好后,运行却没有显示热力图(只有底图),但手工输入的数据却可以生成热力图,不知道是不是组织的格式不对,等之后解决了再上传。

    其他:半径的设置要合理,之前设置为1,结果热力图挤成一团

#4# QGIS

    如果不会写JavaScript,还有方法生成热力图。

    1.将数据转换为csv格式,utf-8编码

    2.打开QGIS,选择【图层】-【添加图层】-【添加文本数据图层】

    (注:这里坐标系为了方便选用了wgs84,但百度的坐标是火星坐标系 ,后续需要进行坐标系转换

        3.打开图层属性,选择符号化,设置为热图,并进行颜色设置

    4.效果如图所示

    QGIS制作热力图教程:製作熱區圖 (QGIS3)

#5# Kepler.gl

    入门基础:Kepler.gl_Dawn_www的博客-CSDN博客_kepler.gl

     注:经纬度字段要用英文lat latitude lng longitude,否则无法自动识别

    

    2020年7月更新:最近又看到一个可以生成热力图的方法:高德开放平台 | Map Lab

# 其他

     免费文件存储分享服务汇总:免费文件存储分享服务汇总 - 梁Sir's Blog

    QGIS:如何美化数据的呈现效果

  • 7
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值