d3.js结合Heatmap.js
2018-01-03 18:30
1496 查看
最近一直在跟gis地图打交道,导师给我的任务是画出所有学校里wifi ap的使用热力图.
于是我接入了百度地图的api,费力地标出了所有wifi ap的坐标信息.最后,导师对百度地图的热力图不甚满意,emmmm.....并给我规定了使用d3.js画热力图.
但是d3所有的热力图都是这样的..
虽然这样的热力图也挺好看的,但是放到我们学校的地图上就不太行了.以下是用d3画我们学校热力图的效果.
但是技术栈又定死了要用d3,怎么办呢?于是我就想能不能在svg上加一层canvas,来实现在d3上画传统热力图的效果.于是就形成了d3.js结合heatmap.js的方案.
首先如何获得可以输入d3的json数据格式?这里推荐WOLFMAP地图下载器,用它的免费功能可以在实景地图上加标注并导出,细节就不多说了,最后导出标注的kml或者kmz文件.
然后放到这个链接 http://2geojson.com/ 里把它转换成d3能接收的geoson格式.
json格式大约是这样的
之后就可以用d3画图了
$(document).ready(function() {
var width = 1300;
var height = 900;
var svg = d3.select("#p1").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(0,0)");
projection = d3.geo.mercator().center([121.43, 31.027]).scale(2100000).translate([width/2, height/2]);
var path = d3.geo.path().projection(projection);
var color = d3.scale.category20();
d3.json("/jsonData/test13.json", function(error, root) {
if (error)
return console.error(error);
console.log(root.features);
svg.selectAll("path")
.data( root.features )
.enter()
.append("path")
.attr("stroke","#000")
.attr("stroke-width",0.5)
.attr("fill", function(d,i){
return "#ffffff";
})
.attr("d", path )
.on("click",function(d,i){alert(d['properties']['Name'])})
.on("mouseover",function(d,i){d3.select(this).attr("fill",function(d,i){
return "#17becf";});
})
.on("mouseout",function(d,i){
d3.select(this)
.attr("fill","#ffffff");
});
});这一套就是d3读取geojson的标准操作,没有什么好多说.重点介绍怎么把heatmap.js覆盖到geojson上.
重点是初始化d3时所申明的这个projection变量,他可以将gis数据转化为当前div中的绝对位置坐标.比如我们现在的中心点设在[121.4,31.024]上,容器的长和宽是[1300,900],那么projection[121.4,31.024]得到的结果就是[650,450].所以说只要能活用这个projection()那么得到任意的gis坐标也可以画到当前的网页中.
接下来就是操作heatmap.js的部分了
下面的程序中,用ajax请求到的数据结构是
['lat': 点的经度,
'lng': 点的纬度,
'count': ap的使用人数]
注意当中有三个坑
第一个是我画d3地图时候用的时google地图,服务器返回的数据的经纬度是基于baidu地图,用projection做映射之后有一定的偏移.
x: Math.round(prolocation[0]-405), y:Math.round(prolocation[1]+190)所以x,y要减去或者加上偏移,不断地调试直到两者重合.
第二个坑就是这边的Math.round,这其实是有关heatmap.js的,因为我发现要是输入点的坐标为float类型,有时候heatmap.js无法正常显示,把他们变成整数后才可以避免这个bug.
第三个坑是d3.js本身是有一些点击事件,mouseon事件的,在上面加了一层canvas后这些事件就无法触发了.解决方法是
这三个坑是我在实践中遇到并解决的.下面是代码
function updateForUtc(){
var targetTime = 1512100800000;
var ACInfo = {
"time": targetTime
};
$.ajax({
url: "/wireless/requestForHeatByTime",
type: "POST",
dataType: "json",
contentType: 'application/json;charset=utf-8',
data: JSON.stringify(ACInfo),
success: function (data) {
var heatmap = h337.create({
container: document.getElementById('p1'),
//gradient: { .1: 'rgba(0,0,0,0)', 0.25: "rgba(0,0,90, .6)", .6: "blue", .9: "cyan", .95: 'rgba(255,255,255,.4)'},
maxOpacity: .6,
radius: 10,
blur: .90
});
var dataList = data['arrayList'];
for(var i=0;i<dataList.length;i++){
var tmp = dataList[i];
var location = [tmp['lng'], tmp['lat']];
var prolocation = projection(location);
heatmap.addData({ x: Math.round(prolocation[0]-405), y:Math.round(prolocation[1]+190), value: Math.round(tmp['count']/10), radius: 20});
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
console.log(XMLHttpRequest);
},
});
}最后上一张结果图
于是我接入了百度地图的api,费力地标出了所有wifi ap的坐标信息.最后,导师对百度地图的热力图不甚满意,emmmm.....并给我规定了使用d3.js画热力图.
但是d3所有的热力图都是这样的..
虽然这样的热力图也挺好看的,但是放到我们学校的地图上就不太行了.以下是用d3画我们学校热力图的效果.
但是技术栈又定死了要用d3,怎么办呢?于是我就想能不能在svg上加一层canvas,来实现在d3上画传统热力图的效果.于是就形成了d3.js结合heatmap.js的方案.
首先如何获得可以输入d3的json数据格式?这里推荐WOLFMAP地图下载器,用它的免费功能可以在实景地图上加标注并导出,细节就不多说了,最后导出标注的kml或者kmz文件.
然后放到这个链接 http://2geojson.com/ 里把它转换成d3能接收的geoson格式.
{ "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": { "Name": "电群1号", "Description": "" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 121.43, 31.02, 0.0 ], [ 121.42, 31.02801, 0.0 ], [ 121.43682025, 31.02, 0.0 ], [ 121.43, 31.0278, 0.0 ], [ 121.435785, 31.027632, 0.0 ] ] ] } } }
json格式大约是这样的
之后就可以用d3画图了
$(document).ready(function() {
var width = 1300;
var height = 900;
var svg = d3.select("#p1").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(0,0)");
projection = d3.geo.mercator().center([121.43, 31.027]).scale(2100000).translate([width/2, height/2]);
var path = d3.geo.path().projection(projection);
var color = d3.scale.category20();
d3.json("/jsonData/test13.json", function(error, root) {
if (error)
return console.error(error);
console.log(root.features);
svg.selectAll("path")
.data( root.features )
.enter()
.append("path")
.attr("stroke","#000")
.attr("stroke-width",0.5)
.attr("fill", function(d,i){
return "#ffffff";
})
.attr("d", path )
.on("click",function(d,i){alert(d['properties']['Name'])})
.on("mouseover",function(d,i){d3.select(this).attr("fill",function(d,i){
return "#17becf";});
})
.on("mouseout",function(d,i){
d3.select(this)
.attr("fill","#ffffff");
});
});这一套就是d3读取geojson的标准操作,没有什么好多说.重点介绍怎么把heatmap.js覆盖到geojson上.
重点是初始化d3时所申明的这个projection变量,他可以将gis数据转化为当前div中的绝对位置坐标.比如我们现在的中心点设在[121.4,31.024]上,容器的长和宽是[1300,900],那么projection[121.4,31.024]得到的结果就是[650,450].所以说只要能活用这个projection()那么得到任意的gis坐标也可以画到当前的网页中.
接下来就是操作heatmap.js的部分了
下面的程序中,用ajax请求到的数据结构是
['lat': 点的经度,
'lng': 点的纬度,
'count': ap的使用人数]
注意当中有三个坑
第一个是我画d3地图时候用的时google地图,服务器返回的数据的经纬度是基于baidu地图,用projection做映射之后有一定的偏移.
x: Math.round(prolocation[0]-405), y:Math.round(prolocation[1]+190)所以x,y要减去或者加上偏移,不断地调试直到两者重合.
第二个坑就是这边的Math.round,这其实是有关heatmap.js的,因为我发现要是输入点的坐标为float类型,有时候heatmap.js无法正常显示,把他们变成整数后才可以避免这个bug.
第三个坑是d3.js本身是有一些点击事件,mouseon事件的,在上面加了一层canvas后这些事件就无法触发了.解决方法是
<style type="text/css"> .heatmap-canvas{ pointer-events:none } </style>
这三个坑是我在实践中遇到并解决的.下面是代码
function updateForUtc(){
var targetTime = 1512100800000;
var ACInfo = {
"time": targetTime
};
$.ajax({
url: "/wireless/requestForHeatByTime",
type: "POST",
dataType: "json",
contentType: 'application/json;charset=utf-8',
data: JSON.stringify(ACInfo),
success: function (data) {
var heatmap = h337.create({
container: document.getElementById('p1'),
//gradient: { .1: 'rgba(0,0,0,0)', 0.25: "rgba(0,0,90, .6)", .6: "blue", .9: "cyan", .95: 'rgba(255,255,255,.4)'},
maxOpacity: .6,
radius: 10,
blur: .90
});
var dataList = data['arrayList'];
for(var i=0;i<dataList.length;i++){
var tmp = dataList[i];
var location = [tmp['lng'], tmp['lat']];
var prolocation = projection(location);
heatmap.addData({ x: Math.round(prolocation[0]-405), y:Math.round(prolocation[1]+190), value: Math.round(tmp['count']/10), radius: 20});
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
console.log(XMLHttpRequest);
},
});
}最后上一张结果图
相关文章推荐
- 结合heatmap.js,在Openlayers中如何实现热力图
- vue中使用heatmapjs的示例代码(结合百度地图)
- heatmap.js 一个用canvas画热力图的利器
- 网页热力图 heatmap js
- heatmap.js 百度地图
- heatmap.js 一个用canvas画热力图的利器
- heatmap.js 一个用canvas画热力图的利器
- heatmap.js 一个用canvas画热力图的利器
- heatmap.js调用百度地图api做热力图
- 热力图实现-heatmap.js 代码示例
- heatmap.js 一个用canvas画热力图的利器
- 热力图制作 heatmap.js+leaflet.js简单例子
- D3.js数据可视化(一)——绘制热图(heat map)
- heatmap.js 一个用canvas画热力图的利器
- jquery与google map api结合使用 控件,监听器
- html5--位置感知(基于js的地理定位geolocation API)结合Google Maps
- asp.net mvc3 结合jquery.pagination.js 实现分页
- Asp.Net结合JS在图层上显示记录信息
- js中生成map对象的方法
- [RxJS] Use RxJS mergeMap to map and merge high order observables