[轉]C#調用百度地圖API經驗分享(四)


這一篇,記錄一下我調用的地圖API實現的功能。下面介紹的都是一些片段的節選,不能直接復制就運行。在實現之前肯定要加載地圖,先放一個webbroser控件,然后如下:

 

private void Form1_Load(object sender, EventArgs e)  
        {  
  
            string str_url = Application.StartupPath + "\\最終合並版本(昨晚修改).html";  
            Uri url = new Uri(str_url);  
            webBrowser1.Url = url;  
            webBrowser1.ObjectForScripting = this;  
                     
        }

 

而為了能與JS交互,首先引入using System.Security.Permissions;,然后在namespace下必須加入兩行:

 

namespace WebBroser_Test_V1._0
{
    [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]

    [System.Runtime.InteropServices.ComVisibleAttribute(true)]


    public partial class Form1 : Form
    {
               public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {

            string str_url = Application.StartupPath + "\\最終合並版本(昨晚修改).html";
            Uri url = new Uri(str_url);
            webBrowser1.Url = url;
            webBrowser1.ObjectForScripting = this;
           // timer1.Enabled = true;         
        }
}

 

有了上面的基礎,就可以實現以下功能了。

1.鼠標放在屏幕上移動時,實時的顯示坐標。

放入一個timer和一個StatusScrip:

 

private void timer1_Tick(object sender, EventArgs e)
        {
            try
            {
                string tag_lng = webBrowser1.Document.GetElementById("mouselng").InnerText;
                string tag_lat = webBrowser1.Document.GetElementById("mouselat").InnerText;
                double dou_lng, dou_lat;
                if (double.TryParse(tag_lng, out dou_lng) && double.TryParse(tag_lat, out dou_lat))
                {
                    toolstatus_CurrentLocation.Text ="當前坐標:"+ dou_lng.ToString("F5") + "," + dou_lat.ToString("F5");
                }
            }
            catch (Exception ee)
            { MessageBox.Show(ee.Message); }
          
        }

 

放入一個button命名及代碼如下:

 

    private void btnGetLocation_Click(object sender, EventArgs e)  
           {  
               if (btnGetLocation.Text == "開啟實時坐標")  
               {  
                   timer1.Enabled = true;  
                   btnGetLocation.Text = "關閉實時坐標";  
               }  
               else  
               {  
                   btnGetLocation.Text = "開啟實時坐標";  
                   timer1.Enabled = false;  
               }  
           }  

 

JS腳本如下:

    var map =new BMap.Map("allmap");  
    var first_locate=new BMap.Point(108.953098,34.2778);  
    map.centerAndZoom(first_locate,15);     
    map.enableScrollWheelZoom(true);  
    map.addEventListener("mousemove",GetlngAndlat);     
    function GetlngAndlat(e)  
    {if(e.point.lng!=null)  
     {  
       
     document.getElementById("mouselng").innerHTML=e.point.lng;  
      document.getElementById("mouselat").innerHTML=e.point.lat;  
     }  
    }  

2.開啟測距工具(百度自己開發的)

拖一個按鈕:

 

    //開啟測距工具按鈕  
            private void btnOpenDistance_Click(object sender, EventArgs e)  
            {  
                webBrowser1.Document.InvokeScript("openGetDistance");  
            }  

 

 

 

 

為了加載這個工具,是需要引入百度的另一個工具庫:

 

JS如下:

 

<script type="text/javascript" src="./JScript/DistanceTool_min.js"></script>
function openGetDistance()
{
 var myDis=new BMapLib.DistanceTool(map);//map為上面已經初始化好的地圖實例
 myDis.open();
}

 

//上面這個DistanceTool_min.js在百度的DEMO里有,我只是把它考到我的DEBUG下了,具體路徑自己解決。

3.右擊鼠標給地圖上放marker,每一個marker的icon換成小汽車,並且顯示坐標編號和坐標值,然后每放置一次,將數據存入數據庫。

//放標注

 

 private void btnPutMarker_Click(object sender, EventArgs e)
        {
            if (radioButton1.Checked || radioButton2.Checked || radioButton3.Checked || radioButton4.Checked)
                webBrowser1.Document.InvokeScript("PUTANDSEND");
            else
            {
                MessageBox.Show("至少選擇一項!");
            }
        }
        //得到Radiobutton的值
        public string setWhichCar()
        {
            if (radioButton1.Checked)
                return "1";
            if (radioButton2.Checked)
                return "2";
            if (radioButton3.Checked)
                return "3";
            if (radioButton4.Checked)
                return "4";
            return "Erro";
        }
        //將從JS里得到的汽車數據顯示到文本框內,並且存入數據庫
        public void PutIntotextBox(object markerIndex,object carNumber,object JSlng,object JSlat)
        {
            text_index.Text =markerIndex.ToString();
            text_num.Text = (string)carNumber;
            text_lng.Text = JSlng.ToString();
            text_lat.Text = JSlat.ToString();
            string sql = "insert into 汽車軌跡數據 values ('"+text_num.Text+"','"+text_index.Text+"','"+text_lng.Text+"','"+text_lat.Text+"','"+DateTime.Now.ToString()+"')";
            DBfunction.getcom(sql);
            
        }

 

JS腳本如下:

 

//---------------放標注,並且將JS的數據傳送給WINFORM------------
function PUTANDSEND()
{
  map.addEventListener("rightclick",putAndsend);
}
function putAndsend(e)
{
  //放標注
  var p1=new BMap.Point(e.point.lng,e.point.lat);
  var marker = new BMap.Marker(p1,{icon:myIcon});//將標注的圖標改為小汽車
  map.addOverlay(marker);
  marker_num++;//標注索引,這個是個全局變量
  var whichCar=window.external.setWhichCar();
  var label=new BMap.Label(whichCar+"號車-坐標"+marker_num+":"+
"("+e.point.lng+","+e.point.lat+")",{offset:new BMap.Size(20,-10)});
  marker.setLabel(label);
  //給WINFORM傳值
  window.external.PutIntotextBox(marker_num,whichCar,e.point.lng,e.point.lat);
  
}

 

4.根據上面已經模擬的汽車歷史坐標,可以查詢具體車輛的歷史軌跡(即從數據庫里提取數據,畫軌跡)

 

private void btnDrawOrit_Click(object sender, EventArgs e)
        {
            string ss = "^[0-9]*$"; //正則表達式
            string cc = text_whichCar.Text.Trim().ToString();
            bool match = Regex.IsMatch(cc, ss);
            if (Convert.ToInt32(text_whichCar.Text) > 4 || !match||text_whichCar.Text.Trim().Equals(String.Empty))
            // webBrowser1.Document.InvokeScript("PUTANDSEND");
            {
                MessageBox.Show("您輸入的不是數字,或者編號不在范圍內!");
            }
            else
            {
                string getdata_sql = "select * from 汽車軌跡數據 where 汽車編號=" + text_whichCar.Text;
                whichCarData(getdata_sql);
            }
        }

 

//從數據庫里的取出經緯度傳送給JS

 

 public void whichCarData(string limit_sql)
        {      
                OleDbDataReader DR = DBfunction.getread(limit_sql);
                ArrayList a = new ArrayList();
                while (DR.Read())
                {
                    a.Add(DR[2]);//經度
                    a.Add(DR[3]);//緯度
                    Rows_Num++;
                }
                if (Rows_Num == 0)
                    MessageBox.Show("該車輛,無歷史信息!");
                else
                {
                    for (int i = 0; i <= 2 * Rows_Num - 1; i++)
                    {
                        pointArr[i] = Convert.ToDouble(a[i]);
                    }

                    webBrowser1.Document.InvokeScript("DrawOrit1");
                }
        }
       //輔助方法
        //獲取計數
        public int getRowsNumber()
        {
            return Rows_Num;
        }
 //根據索引獲取特定坐標
        public double Getpoints(int index)
        { return pointArr[index]; }

 

JS腳本如下:

//------------從后台數據庫獲得點集合來畫軌跡(無參數版本),測試可用

function DrawOrit1()
{
 var Array=[];
var total_num= window.external.getRowsNumber();
for(var i=0;i<=2*total_num-1;i++)
{
 Array.push(window.external.Getpoints(i));
}

var PointArr=[];
for(var i=0;i<=Array.length-1;i+=2)
{//偶數索引存經度,奇數存維度
  PointArr.push(new BMap.Point(Array[i],Array[i+1]));
}
var polyline = new BMap.Polyline(PointArr, {strokeColor:"blue", strokeWeight:6,   strokeOpacity:0.5});  //定義折線
  map.addOverlay(polyline);
window.external.ClearRows_num();//重置窗體計數器
}

5.打開繪圖工具,這個工具可以畫直線,圓,矩形等等,其中我這里用的主要是畫圓的方法,畫好圓后,可以得到哪些車輛在這個圓內,並將其標注出來(其實就是一個預警范圍)。 //開啟畫圖工具按鈕

 

  private void btnDrawPicture_Click(object sender, EventArgs e)
        {
            if (radio_Circle.Checked)
            { webBrowser1.Document.InvokeScript("drawCircle"); }
            else
            { webBrowser1.Document.InvokeScript("drawRec"); }
        }

 

 //搜索當前車輛位置,返回各個車輛的坐標

 

public double SearchAllCars(int index)
        {
           
            string sql="select * from 汽車軌跡數據";
            OleDbDataReader dr= DBfunction.getread(sql);
           ArrayList allCars = new ArrayList();
            while (dr.Read())
            {
                allCars.Add(dr[2]);
                allCars.Add(dr[3]);
            }
            Danger_Num = allCars.Count;
            double[] sendto_JS = new double[allCars.Count];
            allCars.CopyTo(sendto_JS);
           
                return sendto_JS[index];
        }
//全局變量,返回有危險的車輛個數
        public int GetdangerNum()
        { return Danger_Num; }

 

JS腳本如下:

 

<!--加載鼠標繪制工具-->
<script type="text/javascript" src="http://api.map.baidu.com/library/DrawingManager/1.4/src/DrawingManager_min.js"></script>
<link rel="stylesheet" href="http://api.map.baidu.com/library/DrawingManager/1.4/src/DrawingManager_min.css" />
//回調獲得覆蓋物的信息(修改后的版本,已測試可用)
    var complete=function(e)
   {
    overlays.push(e.overlay);
    if (e.drawingMode == BMAP_DRAWING_CIRCLE) 
          {
            //隨便賦值,刷新一遍數據庫(此方法只為演示,實際中要另考慮算法)
          var test=  window.external.SearchAllCars(0);
           
           
         var circle_radius=e.overlay.getRadius();//半徑
          //圓心
         var circle_point=new BMap.Point(e.overlay.getCenter().lng,e.overlay.getCenter().lat);
         //從WINFORM里取出數據
         var dangerCars=[];
         var pointlen=window.external.GetdangerNum();
 
         for(var k=0;k<=pointlen-1;k++)
          {
             dangerCars.push(window.external.SearchAllCars(k));
          }
         var BMappoints=[];//創建百度地圖接口規定的數組
         for(var j=0;j<=dangerCars.length-1;j+=2)
          {
            BMappoints.push(new BMap.Point(dangerCars[j],dangerCars[j+1]));
          }
          
          for(var i=0;i<=BMappoints.length-1;i++)
          {
            if(map.getDistance(circle_point,BMappoints[i])<=circle_radius)
            {
               AddMarker(BMappoints[i]);//調用添加標注版本V3.0
            }    
          }
          
        }
          
      };
//線條樣式
    var styleOptions = {
        strokeColor:"blue",    //邊線顏色。
        fillColor:"blue",      //填充顏色。當參數為空時,圓形將沒有填充效果。
        strokeWeight: 3,       //邊線的寬度,以像素為單位。
        strokeOpacity: 1,    //邊線透明度,取值范圍0 - 1。
        fillOpacity: 0.3,      //填充的透明度,取值范圍0 - 1。
        strokeStyle: 'solid' //邊線的樣式,solid或dashed。
    }
    //實例化鼠標繪制工具
    var drawingManager = new BMapLib.DrawingManager(map, {
        isOpen: true, //是否開啟繪制模式
        enableDrawingTool: true, //是否顯示工具欄
        drawingToolOptions: {
            anchor: BMAP_ANCHOR_TOP_RIGHT, //位置
            offset: new BMap.Size(5, 5), //偏離值
            scale: 0.8, //工具欄縮放比例
            drawingTypes : [         
            BMAP_DRAWING_CIRCLE,  
            BMAP_DRAWING_RECTANGLE 
         ]

        },
        circleOptions: styleOptions, //圓的樣式 
        rectangleOptions: styleOptions //矩形的樣式
    });

    
    
    //添加鼠標繪制工具監聽事件,用於獲取繪制結果
   drawingManager.addEventListener('overlaycomplete',complete);
    
 //drawingManager.enableCalculate();

    
    //----------------------公用方法,用元素id獲取元素的值-------------------
    function $(id){
        return document.getElementById(id);
    }

    //------------------畫矩形,讓WINFORM調用---------------
    function drawRec(){
drawingManager.setDrawingMode(BMAP_DRAWING_RECTANGLE);}
    //------------------畫圓,讓WINFORM調用----------------
     function drawCircle(){
drawingManager.setDrawingMode(BMAP_DRAWING_CIRCLE);}
    //------------------清除所有已畫圖形,讓WINFORM調用--------------------
    function clearAll() {
        for(var i = 0; i < overlays.length; i++){
            map.removeOverlay(overlays[i]);
        }
        overlays.length = 0
    }

 

   這個功能比較復雜,必須要加入前兩行的庫連接才可以。因為畫圓可以得到圓心和半徑,所以我只需要從數據庫里取出點,然后一一測量其與圓心的距離,然后和半徑比較,只要小於半徑則就在圓內標注。起初頭讓我畫矩形,畫矩形的DEMO如下:

 

//回調獲得覆蓋物信息,未使用該版本
    var overlaycomplete = function(e){
        overlays.push(e.overlay);
        var result = "";
       
        result += e.drawingMode + ":";
       
        if (e.drawingMode == BMAP_DRAWING_CIRCLE) {
           
            var circle_radius=e.overlay.getRadius();
            var circle_point=new BMap.Point(e.overlay.getCenter().lng,e.overlay.getCenter().lat);
            alert(map.getDistance(circle_point,tests[1]));
             for(var i=0;i<3;i++)
          {
            if(map.getDistance(circle_point,tests[i])<=circle_radius)
            {
               AddMarker(tests[i]);
            }    
          }
            alert(result);
        }
        if (e.drawingMode == BMAP_DRAWING_POLYLINE || e.drawingMode == BMAP_DRAWING_POLYGON || e.drawingMode == BMAP_DRAWING_RECTANGLE) {
            result += ' 所畫的點個數:' + e.overlay.getPath()[1].lng;
            alert(result);
        }
        
    };

 

 

    這里是修改的百度DEMO,其中有一行result += ' 所畫的點個數:' + e.overlay.getPath()[1].lng;在百度原有的demo里是這樣寫的result += ' 所畫的點個數:' + e.overlay.getPath().length;只會返回一個數據,我仔細看了下函數名,getPath(),而且還有length的屬性,那么 肯定是數組,而且是返回的邊或者點的個數,而邊一定是由點組成的,根據之前的Ployline函數可以推測,這個函數必定是一個存放多邊形點的數組,那么 我就試了試e.overlay.getPath()[1].lng,看能不能取到某個點的經度值,果然不出我所料,可以的,當時興奮了好一陣子,有了這個 方法,矩形的四個點就都能記錄,那么就可以跟數據庫里取出的點直接進行經緯度比較,也可以標注預警范圍,不過還是沒有用圓方便。

    由於時間確實很緊,手頭還有事要做,只能寫到這里了,歡迎交流,噴也行,哈哈。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM