C#调用百度地图API经验分享(四)

来源:互联网 发布:淘宝客服如何分流 编辑:程序博客网 时间:2024/05/16 01:55

    这一篇,记录一下我调用的地图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,看能不能取到某个点的经度值,果然不出我所料,可以的,当时兴奋了好一阵子,有了这个方法,矩形的四个点就都能记录,那么就可以跟数据库里取出的点直接进行经纬度比较,也可以标注预警范围,不过还是没有用圆方便。

    由于时间确实很紧,手头还有事要做,只能写到这里了,欢迎交流,喷也行,哈哈。