# 原理
热力图原理:为离散点信息创建一个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