WPF嵌入百度地圖完整實現

      不管是作App仍是web開發,不少都會用到地圖功能,通常都會調用第三方的API實現地圖功能!而正如國內的地圖API提供方,基本上對Android、IOS和web開發提供了很完整的一套API,可是對於桌面應用程序的支持卻不多,國外有開源的地圖項目,可是相對於國內地點的線路查詢以及公交查詢之類的支持和國內的有必定差距(注:可能國外有比較好的,而我沒有找到把)!而用WPF潛入百度地圖,我用的仍是不少人用的方式,那就是用WebBroswer調用web的Javascript API實現地圖的各個功能,所以web上能實現的功能經過WPF基本可以實現!javascript

     首先咱們經過WebBroswer調用web的API所以須要一個百度地圖html網頁,代碼以下:BMap.htmlcss

<!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.jshtml

//去除網頁中的鏈接地址
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控件,代碼以下:java

  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標籤中的數據,解析各種乘車路線,而又考慮到網速的速度,因此用到了指數避讓的方式,讓獲取到的數據儘可能準確,實現以下:web

 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 DoTimer(object sender,EventArgs e)
        //{
        //    this.Dispatcher.Invoke(new Action(() =>
        //    {
        //        HTMLDocument document = (HTMLDocument)this.webBrowser.Document;
        //        string route = document.getElementById("r-result").innerText;
        //        if (string.IsNullOrEmpty(route)) return;
        //        string[] arry = route.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
        //        if (arry.Length == 0)
        //            return;
        //        RouteItemList = new ObservableCollection<RouteItem>();
        //        for (int i = 2; i < arry.Length - 2; i += 2)
        //        {
        //            RouteItem item = new RouteItem();
        //            item.StartPoint = arry[1];
        //            item.EndPoint = arry[arry.Length - 2];
        //            item.Title = arry[i];
        //            string[] ways = arry[i + 1].Split(',');
        //            List<string> list = new List<string>();
        //            StringBuilder sb = new StringBuilder();
        //            for (int j = 0; j < ways.Length; j++)
        //            {
        //                if (ways[j].StartsWith("乘坐") || ways[j].StartsWith("步行"))
        //                {
        //                    sb = new StringBuilder();
        //                    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);
        //        }
        //        IsLoading =false;
              
        //        mDataTimer.Stop();
        //    }));
           
        //}
        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項目中對百度地圖功能的實現,也是對該功能實現的一個總結吧!windows

相關文章
相關標籤/搜索