用百度地图API分析打交通大数据
百度地图API, 文档不全,例子不细致。 在网上还没有太多有用的例子。比如说下面几个需求的解决方案就找不到:
1. 如何用百度地图API查询一个地点的经纬度。
2. 如何用百度地图通过一个经纬度查询商圈和地址。
3.点击百度地图时, 获得点击位置的经纬度。
4. 如果按照时间轴动态显示热力图的变化。
我昨天玩了一下午百度地图javascript API,解决了上面的几个问题,顺道用少量打车用户的抽样数据做一个数据可视化, 给大家提供一个可以参考的例子
首先数据是来自北京市某个周日的出行数据, 其中包含出发地点和到达地点的经纬度。
{"passenger_phone":"XXX","start_location_lng":"116.31414794922","start_location_lat":"40.080762261285","end_location_lng":"116.3363","end_location_lat":"40.07079"}
{"passenger_phone":"XXX","start_location_lng":"116.734490","start_location_lat":"39.903438","end_location_lng":"116.735160","end_location_lat":"39.962470"}
由于数据是从spark里查询出来放在hadoop上,是map后的一个结果, 因此每条数据的间隔符号是换行。这导致我必须在js里把数据文件命名为txt文件, 并且在js里做一些特殊处理。
百度地图API, 因为需要频繁在js里根据鼠标点击获得地理位置和商圈信息, 因此在html创建了一个不可见的container用来加载地图查询模块
<div id="dummy" style ="display:none"></div>
用来加载百度地图javascript model用来查询地理信息。
var bmap4search= new BMap.Map("dummy");
var localSearch = new BMap.LocalSearch(bmap4search);
由于需要找出鼠标点击位置五公里范围内的人数, 因此需要一个计算地理距离的函数。
function rad(d)
{
return d * Math.PI / 180.0;
}
function getDistance(lng1,lat1, lng2,lat2)
{
radLat1 = rad(lat1);
radLat2 = rad(lat2);
a = radLat1 - radLat2;
b = rad(lng1) - rad(lng2);
s=2*Math.asin(
Math.sqrt(Math.pow(Math.sin(a/2), 2.0)+
Math.cos(radLat1)*Math.cos(radLat2)*Math.pow(Math.sin(b/2), 2.0)));
EARTH_RADIUS = 6378.137;
s = s * EARTH_RADIUS;
s = Math.round(s*10000) / 10000;
return s;
}
页面加载后, 首先显示用户出发热力图, 看上去回龙观还真像是北京的宇宙中心, 出行用户最密集。
用鼠标点击地图上的某一个点, 可以获得该点的地址信息。参考下一张图。
用鼠标点击回龙观位置, 动态获得一个坐标后, 按钮“点击显示5公里内......”亮了。 点击按钮可以查看这些回龙观的用户, 周日出行目的地是哪里。结果发现回龙观的群众周末大多数也只在回龙观附近晃荡。
至于播放时间轴热力图变化的问题, 其实是通过重新设置option时间的,方法与上图完全相同
myChart.setOption(map_option);
下面几张图是回龙观群众在临晨1点~5点按时间轴变化的出行热力图
临晨3点
临晨5点
早晨7点
可以看到上面亮了几个点, 放大地图看看。
发现分别是, 汉王大厦, 融泽嘉园售楼处, 回龙观镇医院。还有一个高速公路收费站口
下面是部分代码。
<!DOCTYPE html>
<html style="height: 100%">
<head>
<meta charset="utf-8">
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=ZUONbpqGBsYGXNIYHicvbAbM"></script>
</head>
<body style="height: 100%; margin: 0">
<div style ="z-index=999">
<input type="button" value="点击切换到出发热力图" onclick="chg(0)" disabled=disabled ID="startBtn" NAME="Button1">
<input type="button" value="点击切换到到达热力图" onclick="chg(1)" ID="endBtn" NAME="Button1">
</div>
<div>
<div id=mytips style="z-order=999;background-color:#F0F8FF;width:100;height:16;border:2px solid gray;display:none;filter:progid:DXImageTransform.Microsoft.Shadow(color=#666666,direction=135,strength=5);left:5;top:5"></div>
<input type="button" value="点击显示5公里内嘀嘀新客的目的地或者来源" disabled=disabled onclick="showDS()" ID="src_dest_Btn" NAME="Button1">
</div>
<div id="dummy" style ="display:none"></div>
<div id="container" style="height: 100%">
</div>
<!-- 新添加的jQuery -->
<script type="text/javascript" src="./js/jquery-3.1.0.js"></script>
<!-- End -->
<script type="text/javascript" src="./js/echarts.js"></script>
<script type="text/javascript" src="./js/dataTool.js"></script>
<script type="text/javascript" src="./js/bmap.js"></script>
<script type="text/javascript">
var bmap4search= new BMap.Map("dummy");
var localSearch = new BMap.LocalSearch(bmap4search);
var dom = document.getElementById("container");
var myChart = echarts.init(dom);
var app = {};
option = null;
app.title = '热力图与百度地图扩展';
var startPoints=[];
var endPoints=[];
var dsPoints=[];
var radium=5;
var gc = new BMap.Geocoder();
var map_option;
var map_status="default";//全部乘客的出发或者达到
//$.get('./js/data/bejing_track_end.json', function (data) {
$.get('./js/data/test.txt', function (data) {
var array = data.split('\n');
for(var i in array)
{
if(array[i]!="")
{
eval("temp="+array[i]);
startPoints[i]=[temp.start_location_lng, temp.start_location_lat].concat([1]);
endPoints[i]=[temp.end_location_lng, temp.end_location_lat].concat([1]);
}
}
option_start = {
animation: true,
bmap: {
center: [116.301670, 39.971690],
zoom: 11,
roam: true
},
visualMap: {
show: false,
top: 'top',
min: 0,
max: 5,
seriesIndex: 0,
calculable: true,
inRange: {
color: ['blue', 'blue', 'green', 'yellow', 'red']
}
},
series: [{
type: 'heatmap',
coordinateSystem: 'bmap',
data: startPoints,
pointSize: 10,
blurSize: 6
}]
}
option_end = {
animation: true,
bmap: {
center: [116.301670, 39.971690],
zoom: 11,
roam: true
},
visualMap: {
show: false,
top: 'top',
min: 0,
max: 5,
seriesIndex: 0,
calculable: true,
inRange: {
color: ['blue', 'blue', 'green', 'yellow', 'red']
}
},
series: [{
type: 'heatmap',
coordinateSystem: 'bmap',
data: endPoints,
pointSize: 10,
blurSize: 6
}]
}
//用来展示5公里范围的人都去到那里, 或者从哪里来的。
option_ds = {
animation: true,
bmap: {
center: [116.301670, 39.971690],
zoom: 11,
roam: true
},
visualMap: {
show: false,
top: 'top',
min: 0,
max: 5,
seriesIndex: 0,
calculable: true,
inRange: {
color: ['blue', 'blue', 'green', 'yellow', 'red']
}
},
series: [{
type: 'heatmap',
coordinateSystem: 'bmap',
data: dsPoints,
pointSize: 10,
blurSize: 6
}]
}
var callback=function(center_point){
option_start.bmap.center = [center_point.lng, center_point.lat];
option_end.bmap.center = [center_point.lng, center_point.lat];
option_ds.bmap.center = [center_point.lng, center_point.lat];
map_option=option_start;
myChart.setOption(map_option);
var bmap = myChart.getModel().getComponent('bmap').getBMap();
bmap.addEventListener("click", function(e){ //鼠标点击事件
var pt = e.point;
if(map_status=="default")
$("#src_dest_Btn").removeAttr("disabled");
else
$("#src_dest_Btn").attr("disabled","disabled");
seashowtip(1, pt.lng,pt.lat);
}
);
if (!app.inNode) {
// 添加百度地图插件
bmap.addControl(new BMap.MapTypeControl());
}
}
searchByStationName("北京",callback);
});
function chg(type)
{
map_status="default";
if(type==0)
{
map_option = option_start;
$("#endBtn").removeAttr("disabled");
$("#startBtn").attr("disabled","disabled");
}else
{
map_option = option_end;
$("#startBtn").removeAttr("disabled");
$("#endBtn").attr("disabled","disabled");
}
$("#src_dest_Btn").attr("disabled","disabled");
myChart.setOption(map_option);
var my_tips=document.all.mytips;
my_tips.style.display="none";
};
function showDS()
{
//显示5公里范围内的新客的目的地或者来源。
if(dsPoints && dsPoints.length>0)
{
map_status="passenger_within5km";
$("#startBtn").removeAttr("disabled");
$("#endBtn").removeAttr("disabled");
option_ds.series[0].data=dsPoints;
map_option=option_ds;
myChart.setOption(map_option);
}
}
function calPopulationAround2(ln, la)
{
var result=[];
var points = map_option.series[0].data;
for(var i in points)
{
var track = points[i];
if(getDistance(track[0],track[1], ln, la)<radium/2)
{
result[index] = track;
index+=1;
}
}
return result;
};
function calPopulationAround(ln, la)
{
//计算5公里内的乘客坐标, 以及他们的来源或者目的地。
if(map_status!="default")
return calPopulationAround2(ln, la);
var result=[];
var points = startPoints;
var ds_points = endPoints;
if(!$("#startBtn").attr("disabled"))
{
points = endPoints;
ds_points=startPoints;
}
dsPoints=[];
var index=0;
for(var i in points)
{
var track = points[i];
if(getDistance(track[0],track[1], ln, la)<radium/2)
{
result[index] = track;
dsPoints[index] = ds_points[i];
index+=1;
}
}
return result;
};
function seashowtip(flag,ln,la){
var my_tips=document.all.mytips;
var points= calPopulationAround(ln,la);
searchByPoint(ln,la, function(result){
var tipsName = ""+result.address+",附近商圈:("+ result.business +"),坐标("+ln+","+la+")周围"+radium+"公里范围内首单人数:"+points.length+"人";
if(flag){
my_tips.innerHTML=tipsName;//为div块上添加内容
my_tips.style.display="";
my_tips.style.width=150;
my_tips.style.zIndex=999;
my_tips.style.display="block";
//my_tips.style.left=event.clientX+10+document.body.scrollLeft;
//my_tips.style.top=event.clientY+document.body.scrollTop;
}else{
my_tips.style.display="none";
}
});
}
function rad(d)
{
return d * Math.PI / 180.0;
}
function getDistance(lng1,lat1, lng2,lat2)
{
radLat1 = rad(lat1);
radLat2 = rad(lat2);
a = radLat1 - radLat2;
b = rad(lng1) - rad(lng2);
s=2*Math.asin(
Math.sqrt(Math.pow(Math.sin(a/2), 2.0)+
Math.cos(radLat1)*Math.cos(radLat2)*Math.pow(Math.sin(b/2), 2.0)));
EARTH_RADIUS = 6378.137;
s = s * EARTH_RADIUS;
s = Math.round(s*10000) / 10000;
return s;
}
function searchByStationName(keyword, cb) {
//var keyword = "石景山区";
//根据地址来查询经纬度。
localSearch.setSearchCompleteCallback(function (searchResult) {
var poi = searchResult.getPoi(0);
cb(poi.point);
});
localSearch.search(keyword);
}
function searchByPoint(lng,lat, cb)
{//根据经纬度查询地址
var poi= new BMap.Point(lng,lat);
gc.getLocation(poi, function(rs){
cb(rs);
});
}
</script>
</body>
</html>
用百度地图API分析打交通大数据的更多相关文章
- 【百度地图API】今日小年大进步,齐头共进贺佳节——API优化升级上线,不再增加内存消耗
原文:[百度地图API]今日小年大进步,齐头共进贺佳节--API优化升级上线,不再增加内存消耗 任务描述: 今天是2011年01月26日,小年夜.百度地图API在小年夜献给广大API爱好者一份给力的礼 ...
- 【百度地图API】情人节求爱大作战——添加标注功能
原文:[百度地图API]情人节求爱大作战--添加标注功能 任务描述: 2月2日是除夕,2月14立马来!即将到来的情人节,你想送TA一份什么礼物呢? 不如,在你们居住的地方,画个大大的桃心,表达你对TA ...
- aaronyang的百度地图API之LBS云[把数据丰富显示1/3]
中国的IT 需要无私分享和贡献的人,一起努力 本篇博客来自地址:http://www.cnblogs.com/AaronYang/p/3673933.html,请支持原创,未经允许不许转载 一.第一步 ...
- 【百度地图API】如何利用地图API制作汽车沿道路行驶的动画?——如何获得道路层数据
原文:[百度地图API]如何利用地图API制作汽车沿道路行驶的动画?--如何获得道路层数据 有几个做汽车导航的朋友问我说,他们想在地图上制作一辆车沿着道路行驶的动画.可是,百度地图的道路数据并没有公开 ...
- 透过【百度地图API】分析双闭包问题
原文:透过[百度地图API]分析双闭包问题 摘要: 有位API爱好者问到,昨天的教程里为什么不使用for循环?他使用for循环后,也发现代码无效.这是什么原因? ------------------- ...
- 【百度地图API】自定义可编辑的交通路线
原文:[百度地图API]自定义可编辑的交通路线 任务描述: 我想自己绘制一条从地铁站出口到天安门的道路,而且还需要根据我的喜好来改变这条路线. 如何实现: 鼠标左击地图,绘制路线:双击后,绘制结束:绘 ...
- 百度地图API开发指南
简介什么是百度地图API? 百度地图API是一套由JavaScript语言编写的应用程序接口,它能够帮助您在网站中构建功能丰富.交互性强的地图应用.百度地图API包含了构建地图基本功能的各种接口,提供 ...
- 深入浅出百度地图API开发系列(3):模块化设计
在前面两张简单介绍了百度地图API的基础知识和使用之后,我们来分析一下百度地图API的基本架构,了解一下基本架构可以帮助我们更清晰的了解API的功能和调用过程,也就可以帮助我们在实际开发中可以更方便的 ...
- 用百度地图API打造方便自己使用的手机地图
有钱人咱就不说了,因为偶是个穷银--因为穷,所以去年买的Huawei C8650+到现在还在上岗,对于没有钱买好的配置的手机的童鞋来说,类似于百度,谷歌,高德等商家的地图在自己的机器上跑起来确实是有点 ...
随机推荐
- HP服务器设置iLO
HP服务器设置iLO步凑 1.开机出现界面—按下F11进入Boot Menu: 2.选择Generic USB Boot回车: 3.选择System Configuration回车: 4.选择iLO ...
- mysql 开发基础系列14 字符集
字符集是一套文字符号及其编码,比较规则的集合.第一个字符集是ascll(american standard code for information interchange). 1. 选择合适的字 ...
- 2019年2月备战春招最新大数据+Java岗位+人工智能岗位资料免费送【限时领取】
不多说,直接上干货! 欢迎大家,关注微信扫码并加入我的3个微信公众号: 大数据躺过的坑 Java从入门到架构师 人工智能躺过的坑 每天都有大量的学习视频资料和精彩 ...
- [java] 为什么重写equals()必须要重写hashCode()
本文版权归 远方的风lyh和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 在Java API文档中关于hashCode方法有以下几点规定(原文来自java深入解析一书) 1 在j ...
- 使用Domain-Driven创建Hypermedia API
在现实中我们会遇到各种各样的复杂场景,"There is not a right way" 用来描述API的设计方法再合适不过了,没有一种API设计方式可以应对所有的场景.区别于& ...
- HttpServetRequest读取body只能一次的问题
HTTP请求中的是字符串数据: //字符串读取 void charReader(HttpServletRequest request) { BufferedReader br = request.ge ...
- 教你一个vue小技巧,一般人我不说的
本文由云+社区发表 1. 需求 最近的项目中,需要实现在vue框架中动态渲染带提示框的单选/多选文本框,具体的效果如下图所示,在输入框聚焦时,前端组件通过接收的kv参数渲染出选项,用户点击选项,可以将 ...
- NET Core微服务之路:弹性和瞬态故障处理库Polly的介绍
前言 上一节中我们介绍了Ocelot的常见使用配置,通过json配置文件,实现API网关的请求处理.和一个使用DownStream扩展下游中间件,来实现Http转RPC的简单实现,功能不算强大,但可以 ...
- sharding:谁都能读懂的分库、分表、分区
本文通过大量图片来分析和描述分库.分表以及数据库分区是怎样进行的. 1.sharding前的初始数据分布 在本文中,我打算用高考考生相关信息作为实验数据.请无视表的字段是否符合现实,也请无视表的设计是 ...
- GNU C 与 ANSI C(下)
1. 语句表达式 GNU C 把包含在括号中的复合语句看做是一个表达式,称作语句表达式,它可以出现在任何允许表达式的地方.我们可以在语句表达式中使用原本只能在复合语句中使用的循环.局部变量等,例如: ...