您的位置:首页 > 其它

WPF 嵌入百度地图完整实现详解

2016-03-21 17:36 267 查看
无论是做App还是web开发,很多都会用到地图功能,一般都会调用第三方的API实现地图功能!而正如国内的地图API提供方,基本上对Android、IOS和web开发提供了很完整的一套API,但是对于桌面应用程序的支持却很少,国外有开源的地图项目,但是相对于国内地点的线路查询以及公交查询之类的支持和国内的有一定差距(注:可能国外有比较好的,而我没有找到把)!而用WPF潜入百度地图,我用的还是很多人用的方式,那就是用WebBroswer调用web的Javascript API实现地图的各个功能,因此web上能实现的功能通过WPF基本能够实现!

首先我们通过WebBroswer调用web的API因此需要一个百度地图html网页,代码如下:BMap.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
body, html,#allmap {width: 100%;height: 100%;overflow: hidden;margin:0;}
#l-map{height:100%;width:88%;float:left;border-right:2px solid #bcbcbc;}
#r-result{height:100%;width:10%;float:left;}
.anchorBL {
display: none;
}
</style>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=CE44c78c410e2c801253586c748d43f6"></script>
<script type="text/javascript" src="http://api.map.baidu.com/library/DistanceTool/1.2/src/DistanceTool_min.js"></script>
<script type="text/javascript" src="http://api.map.baidu.com/library/DrawingManager/1.4/src/DrawingManager_min.js"></script>
<script type="text/javascript" src="ConfigurationMap.js"></script>
<script type="text/javascript" src="api.js"></script>
<link rel="stylesheet" href="http://api.map.baidu.com/library/DrawingManager/1.4/src/DrawingManager_min.css" />
<title>BMap.Net</title>
</head>
<body>

<div id="geo" style="display:none"></div>
<div id="lng" style="display:none"></div>
<div id="lat" style="display:none"></div>
<div id="allmap"></div>
<div id="r-result" style="display:none"></div>
<div id="l-result" style="display:none"></div>
<!--百度地图带着自己的logo,通过下面的方试可以非常简单的移除掉百度地图logo和版权说明-->
<input type="button" onclick="$('#map div.anchorBL').hide();" value="移除地图LOGO和版权说明" />
</body>
</html>
<script type="text/javascript">
//显示一个最简单的地图
var map = new BMap.Map("allmap", { enableMapClick: false });
var lgt = GetLgt();
var lat = GetLat();
var zoom = GetZoom();
map.enableScrollWheelZoom();
map.centerAndZoom(new BMap.Point(lgt, lat), zoom);
map.addControl(new BMap.NavigationControl());
//map.addControl(new BMap.ScaleControl());         // 添加比例尺控件
//map.addControl(new BMap.OverviewMapControl());   //添加缩略地图控件
</script>


上述代码中通过添加标签很容易的移除了百度地图logo和版权说明!并且引用的Javascript API为2.0版本的,从1.2版本后就添加了网页链接的标签,而我在做项目中是一个触摸屏的项目,是不能允许用户进入桌面进行计算机系统的操作的,操作系统是windows8的系统,需要把网页链接取消,通过下面的js代码实现:api.js
//去除网页中的连接地址

window.onload = inifA;
function inifA(){
for(var i=0; i<document.getElementsByTagName("a").length; i++){
document.getElementsByTagName("a")[i].onclick = function(){return false}
}
}
//*定义必要的公共变量
var maker;//标注对象
var distance;//测距对象
var drawingManager;//绘图对象
var drag;//拖框缩放对象
//绘制工具栏外观设定
var styleOptions = {
strokeColor: "red",    //边线颜色。
fillColor: "red",      //填充颜色。当参数为空时,圆形将没有填充效果。
strokeWeight: 3,       //边线的宽度,以像素为单位。
strokeOpacity: 0.8,       //边线透明度,取值范围0 - 1。
fillOpacity: 0.6,      //填充的透明度,取值范围0 - 1。
strokeStyle: 'solid' //边线的样式,solid或dashed。
}
//*
//*结束//
//*地图基础方法*//
//地图平移
function PanTo(lng, lat)
{
map.panTo(new BMap.Point(lng, lat));
}
//返回当前地图中心坐标
function GetCenter()
{
document.getElementById("lng").innerText = map.getCenter().lng;
document.getElementById("lat").innerText =map.getCenter().lat;
}

//设置当前地图所在城市
function SetCity(CityName)
{
map.setCenter(CityName);
}

//将地图放大一级
function ZoomIn()
{
map.zoomIn();
}

//将地图缩小一级
function ZoomOut() {
map.zoomOut();
}

//添加版权控件
function AddCopyrightControl()
{
map.addControl(new BMap.CopyrightControl());
}

//添加地图类型控件
function AddMapTypeControl()
{
map.addControl(new BMap.MapTypeControl());
}

//添加比例尺控件
function AddScaleControl()
{
map.addControl(new BMap.ScaleControl());
}

//添加缩略图控件
function AddOverviewMapControl()
{
map.addControl(new BMap.OverviewMapControl());
}

//开启滚轮调节地图
function EnableScrollWheelZoom()
{
map.enableScrollWheelZoom();
}

//关闭滚轮调节地图
function DisableScrollWheelZoom() {
map.disableScrollWheelZoom();
}
//*
//*结束*//
//*覆盖物方法*//
//添加一个圆

function AddCirle(lng, lat, r)
{
var circle = new BMap.Circle(new BMap.Point(lng, lat), r);
map.addOverlay(circle);
}
//添加交通流图层
function AddTrafficLayer()
{
var traffic = new BMap.TrafficLayer();
map.addTileLayer(traffic);
}

//添加普通标注
function AddNormalMaker(lng, lat)
{
var marker = new BMap.Marker(new BMap.Point(lng, lat));  // 创建标注
map.addOverlay(marker);
}

//标注开启拖拽
function OpenMakerDraging()
{
marker.enableDragging(true);
}

//标注关闭拖拽
function CloseMakerDraging()
{
marker.disableDragging(true);
}

//添加动画标注
function AddAnimationMaker(lng, lat)
{

}

//添加包含一个标签的标注
function AddLabelMaker(lng, lat, content)
{
var marker = new BMap.Marker(new BMap.Point(lng, lat));  // 创建标注
var label = new BMap.Label(content);
marker.setLabel(label);
}

//添加包含一个信息窗口的标注
function AddWindowMaker(lng, lat, content)
{
var marker = new BMap.Marker(new BMap.Point(lng, lat));  // 创建标注
maker.addEventListener("click", function () {
// 创建信息窗口对象
var info = new BMap.InfoWindow(content);
marker.openInfoWindow(infoWindow);
});
}

//添加城市边界
function SetBoundary(city)
{
var bdary = new BMap.Boundary();
bdary.get(city, function (rs) {       //获取行政区域
map.clearOverlays();        //清除地图覆盖物
var count = rs.boundaries.length; //行政区域的点有多少个
for (var i = 0; i < count; i++) {
var ply = new BMap.Polygon(rs.boundaries[i], { strokeWeight: 2, strokeColor: "#ff0000" }); //建立多边形覆盖物
map.addOverlay(ply);  //添加覆盖物
map.setViewport(ply.getPath());    //调整视野
}
});
}

//添加一个信息窗口
function AddInfoWindow(lng,lat,content)
{
var point=new BMap.Point(lng, lat);
var info = new BMap.InfoWindow(content);
map.openInfoWindow(info,point);
}

//添加一个标注
function AddLabel(lng, lat, content)
{
var point = new BMap.Point(lng, lat);
var label= new BMap.Label(content, { point: point });
}

//*
//*结束*//
//*地图服务*//

//本地搜索

function LocalSearch(keywords)
{
var local = new BMap.LocalSearch(map, {
renderOptions: {
map: map,
autoViewport: true
}
});
local.search(keywords);
}

//周边搜索
function SearchNearby(keywords, center)
{
var local = new BMap.LocalSearch(map, {
renderOptions: {
map: map,
autoViewport: true
}
});
local.searchNearby(keywords, center);
}

//范围搜索
function SearchInBounds(keywords)
{
var local = new BMap.LocalSearch(map, {
renderOptions: {
map: map
}
});
local.searchInBounds(keywords, map.getBounds());
}

//公交导航

function search(start, end, route) {
var transit = new BMap.DrivingRoute(map, {
renderOptions: { map: map, panel: "r-result" },
policy: route
});
transit.search(start, end);
}

//公交策略
function GetTakeTransiteWay(start,end,route)
{
var transit;
transit = new BMap.TransitRoute(map, {
renderOptions: { map: map, panel: "r-result" },
policy: route
})
transit.search(start, end);
}

//步行导航
function GetWalkingRoute(start, end)
{
var walking = new BMap.WalkingRoute(map, {
renderOptions: {
map: map,
autoViewport: true
}
});
walking.search(start, end);
}

//驾车导航
function GetDrivingRoute(start, end,route)
{
var transit = new BMap.DrivingRoute(map, {
renderOptions: { map: map, panel: "r-result" },
policy: route
});
transit.search(start, end);
}

function GetDrivingRouteDate(start,end,route)
{
var options = {
onSearchComplete: function(results){
if (driving.getStatus() == BMAP_STATUS_SUCCESS){
// 获取第一条方案
var plan = results.getPlan(0);

// 获取方案的驾车线路
var route = plan.getRoute(0);

// 获取每个关键步骤,并输出到页面
var s = [];
for (var i = 0; i < route.getNumSteps(); i ++){
var step = route.getStep(i);
s.push((i + 1) + ". " + step.getDescription());
}
//document.getElementById("r-result").innerHTML = s.join("<br/>");
}
}
};
var driving = new BMap.DrivingRoute(map, options);
driving.search("天安门", "百度大厦");
}

function GetInnerText()
{
return document.getElementById("r-result").innerText;
}

function Remove()
{
document.getElementById("r-result").innerText = "";
}

//返回指定坐标所在地址
function GetByPoint(lng, lat)
{
var gc = new BMap.Geocoder();
pt = new BMap.Point(lng, lat);
gc.getLocation(pt, function (rs) {
var addComp = rs.addressComponents;
document.getElementById("geo").innerText = addComp.province + ", " + addComp.city + ", " + addComp.district + ", " + addComp.street + ", " + addComp.streetNumber;
});
}

//返回指定地址的坐标
function GetByAddress(geo)
{
//通过IP定位获取当前城市名称
IP();
var cityName=document.getElementById("geo").innerText
var myGeo = new BMap.Geocoder();
// 将地址解析结果显示在地图上,并调整地图视野
myGeo.getPoint(geo, function (point) {
if (point) {
map.centerAndZoom(point, 16);
map.addOverlay(new BMap.Marker(point));
document.getElementById("lng").innerText = point.lng;
document.getElementById("lat").innerText = point.lat;
}
}, cityName);
}

//IP定位
function IP() {
var myCity = new BMap.LocalCity();
myCity.get(myFun);
function myFun(result) {
var cityName = result.name;
document.getElementById("geo").innerText = cityName;
map.setCenter(cityName);
}
}

//*

//*结束*//

//*地图工具*//

//开启地图测距工具

function DistanceToolOpen()
{
var distance = new BMapLib.DistanceTool(map);//测距组件
distance.open();
}

//关闭地图测距工具
function DistanceToolOpen()
{
distance.close();
}

//开启地图拖拽放大工具
function DragAndZoomOpen()
{
var drag = new BMap.DragAndZoomTool(map);
drag.open();
}

//关闭地图拖拽放大工具
function DragAndZoomOpen()
{
drag.close();
}

//开启地图绘制工具
function DrawingManagerOpen()
{
//实例化鼠标绘制工具
var drawingManager = new BMapLib.DrawingManager(map, {
isOpen: true, //是否开启绘制模式
enableDrawingTool: true, //是否显示工具栏
drawingToolOptions: {
anchor: BMAP_ANCHOR_BOTTOM_RIGHT, //位置
offset: new BMap.Size(5, 5), //偏离值
scale: 0.8 //工具栏缩放比例
},
circleOptions: styleOptions, //圆的样式
polylineOptions: styleOptions, //线的样式
polygonOptions: styleOptions, //多边形的样式
rectangleOptions: styleOptions //矩形的样式
});
}

//关闭地图绘制工具
function DrawingManagerClose()
{
drawingManager.close();
}
//*

//*结束*//
//*地图事件*//


在该js代码中实现了大部分百度地图的Javascript的API,在使用过程中我也只是用了很少的一部分,如需详细了解,请查看百度地图API文档(http://developer.baidu.com/map/),通过上述方式去除了网页的链接地址,防止网页跳转,调用系统的IE浏览器(注:WebBroswer调用的IE的内核),WebBroswer控件在WinForm中就出现了,本来该控件做的就很多问题,但是在WPF中不但没有改善,把WebBroswer控件做的更简单了,所以使用起来让人很不爽,并且不能支持js禁用错误提示的方法,因此在WPF中我们直接在隐藏代码中封装了WinForm的WebBroswer控件,代码如下:
private DispatcherTimer mDataTimer;
System.Windows.Forms.Integration.WindowsFormsHost host = new System.Windows.Forms.Integration.WindowsFormsHost();
System.Windows.Forms.WebBrowser webBrowser = new System.Windows.Forms.WebBrowser();
public MapView()
{
InitializeComponent();
//封装WinForm的WebBroswer
webBrowser.Url = new Uri(Environment.CurrentDirectory+"/Map/BMap.html",UriKind.Absolute);
//禁止弹出JS中的错误信息,否则会在界面上出现很多的JS错误报告
webBrowser.ScriptErrorsSuppressed = true;
webBrowser.Document.Window.Error += new System.Windows.Forms.HtmlElementErrorEventHandler(Window_Error);
host.Child=webBrowser;
Grid.SetRow(host,1);
grid.Children.Add(host);
}


而需要查找步行、乘车路线得实现是通过WebBroswer的调用JS的方式,把路线数据显示在隐藏的Html标签中,通过获取html标签中的数据,解析各类乘车路线,而又考虑到网速的速度,所以用到了指数避让的方式,让获取到的数据尽量准确,实现如下:
private void Search()
{
if (String.IsNullOrEmpty(BeginPosition) || String.IsNullOrEmpty(EndPosition))
return;
this.loadWait.IsShowLoading = true;
RouteItemList.Clear();
if (TakeBus)
{
if (Fast)
this.webBrowser.Document.InvokeScript("GetTakeTransiteWay", new object[] { BeginPosition, EndPosition, "BMAP_TRANSIT_POLICY_LEAST_TIME" });//最少时间
if(LessWalk)
//this.webBrowser.InvokeScript("GetTakeTransiteWay", new object[] { BeginPosition, EndPosition, "BMAP_TRANSIT_POLICY_AVOID_SUBWAYS" });//不乘地铁
this.webBrowser.Document.InvokeScript("GetTakeTransiteWay", new object[] { BeginPosition, EndPosition, "BMAP_TRANSIT_POLICY_LEAST_WALKING" });//最少步行

if(LessChange)
this.webBrowser.Document.InvokeScript("GetTakeTransiteWay", new object[] { BeginPosition, EndPosition, "BMAP_TRANSIT_POLICY_LEAST_TRANSFER" });//最少换乘
}
else
{
if(MinTime)
this.webBrowser.Document.InvokeScript("GetDrivingRoute", new object[] { BeginPosition, EndPosition, "BMAP_DRIVING_POLICY_LEAST_TIME" });

if(MinPath)
this.webBrowser.Document.InvokeScript("GetDrivingRoute", new object[] { BeginPosition, EndPosition, "BMAP_DRIVING_POLICY_LEAST_DISTANCE" });

if(NoExpressWay)
this.webBrowser.Document.InvokeScript("GetDrivingRoute", new object[] { BeginPosition, EndPosition, "BMAP_DRIVING_POLICY_AVOID_HIGHWAYS" });
}

//this.loadWait.IsShowLoading= true;
//mDataTimer = new DispatcherTimer();
//mDataTimer.Tick += new EventHandler(DoTimer);
//mDataTimer.Interval = new TimeSpan(5);
//mDataTimer.Start();

BackgroundWorker worker = new BackgroundWorker();
worker.DoWork +=
new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(
worker_RunWorkerCompleted);
worker.RunWorkerAsync();
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
string route = "";
int n = 1;
while(string.IsNullOrEmpty(route))
{
if (n > 5)
break;

Thread.Sleep(n*1000);
n++;
//HTMLDocument document = (HTMLDocument)this.webBrowser.Document;
//route = document.getElementById("r-result").innerText;
this.Dispatcher.Invoke(new Action(() =>
{
route = this.webBrowser.Document.InvokeScript("GetInnerText").ToString();
}));
}
if (string.IsNullOrEmpty(route))
{
this.Dispatcher.Invoke(new Action(() =>
{
this.loadWait.IsShowLoading = false;
if(TakeBus)
MessageHelper.ShowMessage("提示", "请确定查询地点属于大连,如地点无误则为网络异常,请重新搜索",MessageWin.MessageType.Options);
MessageHelper.ShowMessage("提示", "请确定查询地点正确,如地点无误则为网络异常,请重新搜索!", MessageWin.MessageType.Options);
}));
return;
}
string[] arry = route.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
this.Dispatcher.Invoke(new Action(()=>
{
if (TakeBus)
AnalysisBus(arry);
if (TakeCar)
AnalysisCar(arry);
}));
}

private void AnalysisBus(string[] arry)
{
int n = 0;
for (int i = 2; i < arry.Length - 2; i += 2)
{
n++;
RouteItem item = new RouteItem();
item.StartPoint = arry[1];
item.EndPoint = arry[arry.Length - 2];
item.Title = "第" + n + "种方案:" + arry[i].Remove(0, 2);
string[] ways = arry[i + 1].Split(',');
List<string> list = new List<string>();

StringBuilder sb = new StringBuilder();
int m = 0;
for (int j = 0; j < ways.Length; j++)
{
if (ways[j].StartsWith("乘坐") || ways[j].StartsWith("步行"))
{
m++;
sb = new StringBuilder();
sb.Append(m);
sb.Append(".");
sb.Append(ways[j]);
sb.Append(",");
}
else if (ways[j].StartsWith("经过"))
{
sb.Append(ways[j]);
sb.Append(",");
}
else
{
sb.Append(ways[j]);
list.Add(sb.ToString());
}
}
item.Ways = new ObservableCollection<string>(list);
RouteItemList.Add(item);
};
}
private void AnalysisCar(string[] arry)
{
RouteItem item = new RouteItem();
item.StartPoint = arry[1];
item.EndPoint = arry[arry.Length - 2];
item.Title = "驾车从"+arry[1]+"到"+arry[arry.Length-2]+"路线";
List<string> list = new List<string>();
for (int i = 2; i < arry.Length - 2; i++)
{
list.Add(arry[i]);
};
item.Ways=new ObservableCollection<string>(list);
RouteItemList.Add(item);
}


可以把查询出来的各个信息显示在UI上面,如果还需要其他的功能,可以通过上面的方式,调用不同的Javascript 的API实现!这是个人在WPF项目中对百度地图功能的实现,也是对该功能实现的一个总结吧!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: