前言:

  最近一直在做数据可视化方面的工作,其中平面可视化没什么难度,毕竟已经有很多成熟的可供使用的框架,比如百度的echart.js,highcharts.js等。还有就是3D可视化了,整体来说难度也还好,通过WEBGL技术一般的可视化效果还是很好实现,如果对于WEBGL光线渲染力不从心的话直接通过three.js来做也是很方便。

  其实真正困扰我开发的是可视化项目中一般会存在很多基于地图方面的开发工作,只要是涉及到地图的可视化必然会跟经纬度相关联。如果是单纯获取地图上某个特定城市或者特定点的经纬度这个很好实现,通过 百度地图经纬度拾取系统 便可以很方便的获取到,但是这个系统只能是获取单个点的经纬度,并不能根据地图上的特定轨迹来拾取轨迹对应的经纬度信息。因为在实际开发过程中,地图可视化项目最多的还是在地图上绘制轨迹的需求。举个实际工作中遇到的需求,需要在某城市的地图上绘制出该城市所有地铁线路图,并且在对应站点展示高峰流量。这个需求中特定站点的绘制相对简单,可以通过上述讲的百度地图经纬度拾取系统来获取,但是对应的地铁轨迹的经纬度信息获取就蛋疼了,在网上查询了好久都没能够查询到(可以肯定的是网上肯定有,但是我就是查不到)。

  针对上面所讲的困惑,我就有了想自己制作一个工具的想法,这个工具可以根据用户在地图上绘制的轨迹对应的将轨迹的经纬度信息保存并提供给用户,先不说这个想法是否能够帮助到其他人,至少能够满足我工作的需求。

工具原理说明:

  1 用户在工具集成地图上绘制轨迹(点轨迹,圆轨迹,线轨迹,多边形轨迹,四边形轨迹);

  2 工具内部调用集成地图API获取绘制轨迹的经纬度信息;

  3 将集成地图API返回的经纬度信息展示在工具对应的位置中,每次绘制玩一个轨迹就生成一条经纬度信息;

  4 用户通过工具提供的查看轨迹详情按钮可以查看经纬度信息并且可以直接复制到自己项目中使用;

  5 为了满足项目中一个需求包含多个轨迹的可能性,因此增加了一个合并轨迹经纬度信息的功能。

集成地图选型:

  目前用户群体最大的两个地图是百度和阿里旗下的高德地图,经过比对最终还是选择了百度地图,因为百度地图API中有提供鼠标绘制工具DrawingManager,并且使用简单,API文档也比较完善。

工具界面设计:

  既然集成地图选择了百度地图,那工具界面也就同百度地图界面,界面效果图具体如下:

工具实现代码说明:

1 dom结构说明:

  1.1 main-div 为整体显示框架;

  2.2 search-frame 用于存放搜索内容;

  2.3 travel-frame 用于存放轨迹;

  2.4 setting-frame 用于存放地图皮肤和鼠标绘制工具配置项内容;

  2.5 allmap 用于存放百度地图。

 <div class="main-div">
<div class="search-frame">
<div class="search">
<input class="search-input" placeholder="请输入搜索关键字">
<button class="search-btn"><i class="fa fa-search"></i></button>
</div>
<div class="search-info" style="max-height: 122px;"></div>
</div>
<!-- 轨迹 -->
<div class="travel-frame"> </div>
<!-- 配置项 -->
<div class="setting-frame">
<div class="setting-content" style="">
<div class="setting-list map-theme">
<p>地图皮肤配置</p>
<div class="theme-content clearfix"> </div>
</div>
<div class="setting-list">
<p>地图绘制工具参数配置</p>
<div class="list-content">
<label>边线颜色</label>
</div>
<div class="list-content">
<label>填充颜色</label>
</div>
<div class="list-content">
<label>边线宽度</label>
</div>
<div class="list-content">
<label>边线类型</label>
</div>
</div>
<div class="setting-operate"><i class="fa fa-chevron-down"></i></div>
</div>
<div id="allmap"></div>
</div>

2 js代码说明:

  2.1 首先在代码中引入百度地图API js文件,鼠标操作工具css文件和js文件,具体引用代码如下;

 <link rel="stylesheet" href="http://api.map.baidu.com/library/DrawingManager/1.4/src/DrawingManager_min.css" />
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=您在百度申请的key值"></script>
<script type="text/javascript" src="http://api.map.baidu.com/library/DrawingManager/1.4/src/DrawingManager_min.js"></script>

  2.2 百度地图初始化,地图开启滚轮缩放,默认展示区域为北京。因为实现的工具不需要展示具体点的详情信息,所以需要禁止点击地图的详情弹窗,通过设置enableMapClick = false实现。

 // 百度地图初始化,其中allmap为页面中需要展示地图的id值
var map = new BMap.Map("allmap", {
enableMapClick: false
})
// 开启滚轮缩放
map.enableScrollWheelZoom(true);
// 初始化地图默认显示地点为北京
var point = new BMap.Point(120.12, 30.16);
map.centerAndZoom(point, 13);

  2.3 地图初始化完成后,需要根据用户当前所在地对应的进行地图显示位置切换,该操作需要获取位置信息,需要用户授权。

 // 获取当前用户所在位置信息
var geolocation = new BMap.Geolocation();
// 获取定位,如果获取成功则定位到当前位置,定位不成功使用默认的位置
geolocation.getCurrentPosition(function (r) {
if (this.getStatus() == BMAP_STATUS_SUCCESS) {
map.panTo(r.point);
map.enableScrollWheelZoom(true);
} else {
layer.alert('failde' + this.getStatus());
}
}, {enableHighAccuracy: true})

  2.4 鼠标绘制工具参数说明及鼠标绘制工具实例化。

 // 鼠标绘制巩固配置项及说明
var styleOptions = {
strokeColor: '#ff0000', // 边线颜色。
fillColor: ‘#ff0000’, // 填充颜色,当该参数为空时,圆形/多边形/正方形将没有填充效果。
strokeWeight: 1, // 边线的宽度,以像素为单位,默认为1。
strokeOpacity: 0.8, // 边线的透明度,取值范围为0~1。
fillOpacity: 0.6, // 填充的透明度,取值范围为0~1。
strokeStyle: 'solid' // 边线的样式,可选solid和dashed。
}
// 鼠标绘制工具实例化
var drawingManger = new BMapLib.DrawingManager(map, {
isOpen: false, // 表示是否开启绘制模式
enableDrawingTool: true, // 是否显示工具栏
drawingToolOptions: {
anchor: BMAP_ANCHOR_TOP_RIGHT, // 工具栏显示在右上角
offset: new BMap.Size(5,5) // 工具栏偏移右上角位置
},
circleOptions: styleOptions, // 圆的样式
polylineOptions: styleOptions, // 线的样式
polygonOptions: styleOptions, // 多边形的样式
rectangleOptions: styleOptions, // 矩形的样式
})

  2.5 鼠标绘制工具样式更改和地图皮肤更换。鼠标绘制工具样式更改通过重定义 styleOptions 对应参数来实现,其中边框颜色和填充颜色需要把颜色和透明度分开,地图皮肤切换通过 map.setMapStyle 来实现。

 // 地图皮肤更改代码
$('.theme-list').click(function () {
// 获取地图皮肤类型
var themeName = $(this).data('type');
// 将皮肤类型保存到本地
localStorage.setItem('themeType', themeName);
// 执行更改皮肤操作
map.setMapStyle({
style: themeName
})
})
// 鼠标操作工具配置项更改方法
function changeOptionFun () {
var strokeColorArray = mapOption.borderColor.split(',');
var strokeColor = mapOption.borderColor.indexOf('rgba') != -1 ? 'rgb(' + [strokeColorArray[0].split('(')[1],strokeColorArray[1],strokeColorArray[2]].join(',') + ')' : mapOption.borderColor;
var strokeOpacity = strokeColorArray[3].split(')')[0];
var fillColor = mapOption.fillColor.indexOf('rgba') != -1 ? 'rgb(' + [fillColorArray[0].split('(')[1],fillColorArray[1],fillColorArray[2]].join(',') + ')' : mapOption.fillColor;
var fillOpacity = fillColorArray[3].split(')')[0];
// 参数更新
styleOptions.strokeColor = strokeColor;
styleOptions.fillColor = fillColor;
styleOptions.strokeWeight = Number(mapOption.borderWidth);
styleOptions.strokeOpacity = Number(mapOption.strokeOpacity );
styleOptions.fillOpacity= Number(mapOption.fillOpacity);
styleOptions.strokeStyle= Number(mapOption.borderType);
}

  2.6 鼠标绘制工具添加轨迹绘制完成方法overlaycomplete,该方法中执行轨迹绘制完成后保存绘制轨迹数据到 markerArray 中,对应的需要更新页面中轨迹弹窗中的数据,轨迹新增完成后需要先输入保存轨迹的名称,然后才能执行以后的步骤,如果不输入名称默认不保存该轨迹。

 // 鼠标绘制工具监听事件,用于获取绘制结果并同步绘制结果到页面
var overlaycomplete = function () {
// 需要添加鼠标工具绘制完成之后的逻辑
var removeBool = true;
selectArray = [];
layer.prompt({title: '输入轨迹名称,并确认', formType: 3}, function(text, index){
layer.close(index); if (e.overlay.ia) {
markersArray[new Date().getTime()] = {
location: [{
locationInfo: e.overlay.ia,
name: text
}],
name: text,
overlay: e.overlay
}
} else {
markersArray[new Date().getTime()] = {
location: [{
locationInfo: [e.overlay.point],
name: text
}],
name:text,
overlay: e.overlay
}
}
removeBool = false;
// 赋值轨迹
$('.travle-general b').html(Object.keys(markersArray).length);
// 轨迹循环
var html = '';
for (var list in markersArray) {
var travelNum = 0;
markersArray[list].location.forEach(function (item, index) {
travelNum += item.locationInfo.length;
})
html += '<div class="info-list clearfix">'
+'<div class="info-list-l">'
+' <div class="checkbox-bg"></div>'
+' <input class="checkbox" data-key=' + list + ' type="checkbox" />'
+' <i></i>'
+'</div>'
+'<div class="info-list-r">'
+' <p class="title">' + markersArray[list].name + '</p>'
+' <div class="info-frame clearfix">'
+' <p class="info">共有<span>' + travelNum + '</span>个位置经纬度信息</p>'
+' <button class="travel-info" data-key=' + list + '>详情</button>'
+' <button class="travel-delete" data-key=' + list + '>删除</button>'
+' </div>'
+'</div>'
+'</div>';
}
if (Object.keys(markersArray).length > 1) {
html += '<div class="combine-btn"><button>合并查看详情</button></div>'
}
$('.travle-info').html(html);
});
}
// 鼠标绘制工具添加监听事件
61 drawingManager.addEventListener('overlaycomplete', overlaycomplete);

  2.7 地图搜索功能实现,通过百度地图API中的BMap.LocalSearch来搜索数据,自定义setSearchCompleteCallback方法来实现搜索后页面数据展示的逻辑,搜索数据最多显示十条,需要过滤掉名称一样的数据。

 // 开启百度地图搜索功能
var localSearch = new BMap.LocalSearch(map);
//搜索成功后回调函数定义
localSearch.setSearchCompleteCallback(function (searchResult) {
// 用于存放过滤后的搜索数据
var filterSearchResult = [];
// 存放搜索数据title值,主要用于过滤重复数据使用
var filterSearchResultTitle = [];
// 循环处理获取到的数据,过滤title重复的数据
searchResult.Ar.forEach(function (item) {
if (filterSearchResultTitle.indexOf(item.title) == -1) {
filterSearchResultTitle.push(item.title);
filterSearchResult.push(item);
}
// 此处需要补充代码
})
})
// 搜索方法
function searchByStationName(keyword) {
localSearch.search(keyword);
}

  2.8 已有轨迹删除方法,轨迹删除成功之后需要在对应的轨迹弹窗中将需要删除的轨迹移除,并且如果地图中有该轨迹也需要调用 map.removeOverlay 方法移除地图中的轨迹。

 // 删除轨迹事件
$('.travel-delete').on('click', function () {
var element = $(this);
var key = element.data('key');
layer.confirm('轨迹删除不可恢复,是否删除?', {
btn: ['确认','取消'],
title: '删除轨迹'
}, function(index){
layer.close(index); map.removeOverlay(markersArray[key].overlay);
delete markersArray[key];
element.parents('.info-list').remove();
// 重新赋值轨迹
$('.travle-general b').html(Object.keys(markersArray).length);
}, function(index){
layer.close(index);
});
})

  2.9 查看轨迹详情和合并查看详情需要选中至少两条轨迹,点击之后会弹出轨迹详情弹窗,会将选择的需要合并的轨迹中的数据合并到一起展示,并且通过复制粘贴便可以使用。

 // 合并查看详情事件
$('.combine-btn').off().click(function () {
if (selectArray.length < 2) {
layer.alert('轨迹合并请至少选择两条轨迹');
return false;
}
layer.open({
type: 1,
title: '轨迹经纬度详情(<span style="color:#ff0000;">左边为格式化,右边为未格式化</span>),使用请直接进行复制粘贴操作',
skin: 'layui-layer-rim', //加上边框
area: ['100%', '100%'], //宽高
content: infoHtml
});
var _markersArray = [];
for (var key in markersArray) {
if (selectArray.indexOf(parseInt(key)) != -1) {
_markersArray.push(markersArray[key].location[0]);
}
} $('#code-content-str').html(JSON.stringify(_markersArray));
aceInitFun(formatJson(_markersArray).trim());
})

工具项目预览及体验地址:

  基于百度地图API实现在地图上绘制轨迹并拾取轨迹对应经纬度工具

后话:

  由于平时只有下班时间才能够开发,所以开发这个工具前前后后花费了有将近两周的时间,中间还有个几次通宵的情况,如果工具对您的工作有帮助,或者您对该工具有什么好的建议欢迎留言。

记录开发基于百度地图API实现在地图上绘制轨迹并拾取轨迹对应经纬度的工具说明的更多相关文章

  1. PHP:基于百度大脑api实现OCR文字识别

    有个项目要用到文字识别,网上找了很多资料,效果不是很好,偶然的机会,接触到百度大脑.百度大脑提供了很多解决方案,其中一个就是文字识别,百度提供了三种文字识别,分别是银行卡识别.身份证识别和通用文字识别 ...

  2. 使用百度地图API进行Android地图应用开发(Eclipse)

    随着基于位置的服务的兴起,地图类App呈现爆发趋势.随着而来的是地图供应商开放大量的API.供开发人员开发基于PC或者移动端的应用程序. 如今我们研究使用百度地图SDK进行Android项目的开发. ...

  3. 基于百度翻译API开发属于自己的翻译工具

    你是否每天使用着网页翻译工具?你是否遇到过这种情况,上网过程中遇到一个很长的单词但是又不能复制,要开两个浏览器,一个打开百度翻译,照着另一个网页输入单词?你安装了各种翻译软件后,又删除,只因忍受不了那 ...

  4. 百度地图API和高德地图API资料集锦

    [高德地图API]从零开始学高德JS API(五)路线规划——驾车|公交|步行   [高德地图API]从零开始学高德JS API(四)搜索服务——POI搜索|自动完成|输入提示|行政区域|交叉路口|自 ...

  5. 如何在网中使用百度地图API自定义个性化地图

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  6. 百度地图API,展示地图和添加控件

    1.申请百度账号和AK 点我申请 2.准备页面 根据HTML标准,每一份HTML文档都应该声明正确的文档类型,我们建议您使用最新的符合HTML5规范的文档声明: <!DOCTYPE html&g ...

  7. 基于百度语音识别API的Python语音识别小程序

    一.功能概述 实现语音为文字,可以扩展到多种场景进行工作,这里只实现其基本的语言接收及转换功能. 在语言录入时,根据语言内容的多少与停顿时间,自动截取音频进行转换. 工作示例: 二.软件环境 操作系统 ...

  8. WP8.1小梦词典开发2:百度翻译API使用

    原文出自:http://www.bcmeng.com/api2/ 小梦昨天和大家分享了WP8.1金山词霸API使用方法,今天继续分享windows phone 8.1中百度翻译API的使用方法.和昨天 ...

  9. Android开发基于百度地图的乘车助手

    写在前面: 出去玩免不了挤公交.等地铁,不知道乘车方案当然不行,用官方APP吧,缺点一大堆,手机浏览器在线查的话既慢又麻烦...为了解决这些问题,我们来做一个简版的出行助手,嘛嘛再也不用担心我会迷路了 ...

随机推荐

  1. java之--加密、解密算法

    0.概述 在项目开发中,我们常需要用到加解密算法,加解密算法主要分为三大类: 1.对称加密算法,如:AES.DES.3DES 2.非对称加密算法,如:RSA.DSA.ECC 3.散列算法,如:MD5. ...

  2. Android Jni开发,报com.android.ide.common.process.ProcessException: Error configuring 错误解决方案

    今天在练习JNI项目时,Android studio版本为:3.1.3,Gradle版本为4.4.由于Android studio 3.X弃用了 android.useDeprecatedNdk=tr ...

  3. mysql查询出所有重复的记录

    假如我们有如下一张数据表(很简单,只是举例而已),表名为student.现在我们要取出其中重复记录.重复是以name相同为判定标准. ID name phone age 1 张三 10086 15 2 ...

  4. 华为eNSP路由交换-静态路由

    静态路由 一. 静态路由及默认路由基本配置 1.1实验内容 在由三台路由器所组成的简单网络中,R1和R3各连着一台PC,现在要求能够实现PC-1和PC-2之间的通信.本实验将通过配置基本的静态路由和默 ...

  5. JavaScript的函数申明、函数表达式、箭头函数

    JavaScript中的函数可以通过几种方式创建,如下. // 函数声明 function getName() { return 'Michael' } // 函数表达式 const getName ...

  6. 开发者应该掌握 WebSocekt 协议的知识

    文章介绍 WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,它的出现使客户端和服务器之间的数据交换变得更加简单.WebSocket 通常被应用在实时性要求较高的场景,例如赛事数据. ...

  7. kubernetes学习笔记(三)——利用kubeadm部署集群

    文章目录 (一)安装前准备 (二)master安装 1.安装组件 2.排错 (三)node安装 1.安装组件 2.加入master 3.排错 (四)网络安装 (五)dashboard安装 (一)安装前 ...

  8. Linux下RocketMQ下载安装教程

    一.下载 1.官网下载:下载地址   2.百度网盘下载:下载地址 提取码:0g5a java开发工具下载地址及安装教程大全,点这里. 更多深度技术文章,在这里. 二.安装及启动 1.将zip文件上传到 ...

  9. 第6节:Java基础 - 三大集合(上)

    第6节:Java基础 - 三大集合(上) 本小节是Java基础篇章的第四小节,主要介绍Java中的常用集合知识点,涉及到的内容包括Java中的三大集合的引出,以及HashMap,Hashtable和C ...

  10. 最全的防火墙(firewalld)

    第1章  防火墙的介绍 1.1  防火墙的介绍 1.1.1 概念 动态管理防火墙服务(图形界面和linux界面都可以实现) 支持不同防火墙的区域信息 属于传输层次的防火墙 1.1.2 防火墙的默认规则 ...