百度地图api使用
1.C#窗体中放置WebBrowser控件
-
WebBrowser控件允许我们在里面放置HTML(HyperText Markup Language,超文本标记语言)
-
事实上就是个嵌入的浏览器,当我们写了HTML代码之后,由浏览器帮我们完成渲染,不同浏览器对于HTML的渲染方式大体一样,但是IE和Chrome略有差异,C#内置WebBrowser控件的内核为IE7 见下图
-
控件的Name属性默认为
Name = webBrowser1
-
ScriptErrorsSuppressed = False
该属性用来指示当html页面出错的时候,是否弹出错误提示,如果设置为True则就算html出错不会弹出提示框,建议改为False这样出错就可以及时发现并处理
2. 写Html绘制基础地图
html css javascript三者关系
html是骨架 css是皮肤 js是肌肉
-
需要在百度创建账号成为其开发者,应用类型为浏览器端,然后获取密钥ak
- api的请求格式为: http://api.map.baidu.com/api?v=2.0&ak=您的密钥 v=2.0 即使用的版本
- 一定得需要连网才能请求成功
Html主体部分如下:
<!DOCTYPE html>
<html>
<head>
//控制信息
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Hello, World</title>
//css部分
<style type="text/css">
body, html, #container {
width: 100%;
height: 100%;
overflow: hidden;
margin: 0;
font-family: "微软雅黑";
}
</style>
//javascript部分
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=您的ak">
</script>
</head>
<body>
<div id="container"></div>
<script type="text/javascript">
// 创建地图实例
var map = new BMap.Map("container");
// 创建点坐标
var point = new BMap.Point(102.857476, 24.860112);
// 初始化地图,设置中心点坐标和地图级别
//地图级别用来显示缩放的级别
map.centerAndZoom(point, 16);
//开启鼠标滚轮缩放
map.enableScrollWheelZoom(true);
//不同控件的位置不同
var opts = {
anchor: BMAP_ANCHOR_TOP_LEFT};
map.addControl(new BMap.NavigationControl(opts));
var opts = {
anchor: BMAP_ANCHOR_BOTTOM_RIGHT};
map.addControl(new BMap.ScaleControl(opts));
var opts = {
anchor: BMAP_ANCHOR_TOP_RIGHT};
map.addControl(new BMap.MapTypeControl(opts));
</script>
</body>
</html>
上述代码效果如下:
3.数据库的设计
因为上述代码中设计到了经度和纬度,所以不可避免地需要在数据库中添加lng和lat这两个字段:
具体地经纬度坐标拾取可以通过 这个网站
4.在各个路口放置文字标签
参考 这个网站
实现思路是在树形菜单加载的同时就调用前端javascript完成每个路口文字标注的渲染
- html需要添加以下js函数:
<script charset="utf-8">
function flags(lat, lng, name) {
//将传入的坐标新建一个点
var point = new BMap.Point(lng, lat);
//设置
var opts = {
position: point, // 指定文本标注所在的地理位置
offset: new BMap.Size(10, -10) //设置文本偏移量
}
// 创建文本标注对象,使用name(交叉口的名称)作为标签的内容
var label = new BMap.Label(name, opts);
label.setStyle({
color: "red",
fontSize: "12px",
height: "20px",
lineHeight: "20px",
fontFamily: "微软雅黑"
});
map.addOverlay(label);
}
</script>
- c#中需要调用上面这个js函数,需要传递参数,参数要包装在一个string数组中进行传递。
//调用前端js函数完成路口注释文字的摆放
webBrowser1.Document.InvokeScript("flags", new string[] { sdr.GetDouble("lat").ToString(), sdr.GetDouble("lng").ToString(), sdr.GetString(sdr.GetOrdinal("t_fx1")).ToString() + "-" + sdr.GetString(sdr.GetOrdinal("t_fx2")).ToString() });
- 同时c#窗体中还要加上参数
webBrowser1.ObjectForScripting = this;
才可以允许c#调用前端函数
5.双击树形菜单时地图定位到交叉口位置
只要获取到树形菜单选中的节点,然后调用一个js函数,把这个节点的经度、纬度传给前端,让js完成渲染即可。可以使用节点的Level属性获取该节点的深度,从而完成判断,如果深度为0,则是根节点,如果是1,则为叶子节点。
c#代码如下:
private void treeView1_DoubleClick(object sender, EventArgs e) {
string lat = "for init", lng = "for init";
//获取当前选中的节点
TreeNode cur = treeView1.SelectedNode;
//可能用户没有选中节点,此时cur为null
if (cur != null && cur.Level >= 1) {
MySqlCommand cmd = new MySqlCommand("select * from tlc_jckb where t_id='" + cur.Name + "'", conn);
MySqlDataReader sdr = cmd.ExecuteReader();
if (sdr.Read()) {
//获取经度纬度
lat = sdr.GetString(sdr.GetOrdinal("lat"));
lng = sdr.GetString(sdr.GetOrdinal("lng"));
}
sdr.Close();
//调用javascript完成前端地图的移动
webBrowser1.Document.InvokeScript("setpos", new string[] {
lat, lng });
}
}
相应的html中需要添加js函数:
<script charset="utf-8">
//给出经纬度,定位到那个点
function setpos(lat, lng) {
//将传入的坐标新建一个点
var point = new BMap.Point(lng, lat);
//设置小图像来定位到那个点
map.centerAndZoom(point, 18);
//设置小图像来定位到那个点
var myIcon = new BMap.Icon("icon.png", new BMap.Size(32, 32), {
//相对位置
anchor: new BMap.Size(10, 10)
});
//添加小图标
var marker = new BMap.Marker(point, {
icon: myIcon});
map.addOverlay(marker);
}
</script>
其中的小旗摆放可以参考:这个网站
6.点击地图时c#选中相应节点
-
要想的嵌入的html可以调用c#函数,要设置系统属性
[System.Runtime.InteropServices.ComVisible(true)]
因为前端如果可以调用后端函数操作后端,是很不安全的。 -
在地图的html中加入一个前端js监听
map.addEventListener("click", function (e) { window["external"].judge_pos(e.point.lat, e.point.lng); }
监听点击时间,所以每在地图上点击一下,就会触发这个监听函数,监听的同时收集点击坐标的经度、纬度,然后调用后端c#函数进行处理,judge_pos为c#中的函数。
-
judge_pos函数在c#中的定义
从前端获得了点击的经度和纬度,那么如何判断点击的点是否在已有的交叉口附近呢?
思路是这样的:在c#中定义一个坐标数组,用来存储已有的交叉口的经度和纬度,c#内置已经有这个类了,就是Point类和PointF类,不过要使用PointF类,因为后者支持坐标为小数。然后让前端传回来的经度和纬度与这些交叉口一一比较,如果经度差和纬度差同时小于某个阈值,就认为鼠标单击的是这个路口
public void judge_pos(double lat, double lng) { //允许的经纬度偏差阈值 const double accuracy = 0.002; //遍历每一个路口 for (int i = 1; i <= count; i++) { if (Math.Abs(lat - ptarry[i].X) < accuracy && Math.Abs(lng - ptarry[i].Y) < accuracy) { //找到该路口的node,Find()函数是查找的键 key TreeNode cur = treeView1.Nodes.Find(i.ToString(), true)[0]; //该节点为选中状态 treeView1.SelectedNode = cur; //调用数据库获得路口的名称 MySqlCommand cmd = new MySqlCommand("select * from tlc_jckb where t_id='" + i + "'", conn); MySqlDataReader sdr = cmd.ExecuteReader(); if (sdr.Read()) { lkm1 = sdr.GetString(sdr.GetOrdinal("t_fx1")); //路口方向街名1 lkm2 = sdr.GetString(sdr.GetOrdinal("t_fx2")); //路口方向街名2 } sdr.Close(); //弹出消息框提示 MessageBox.Show("已经选中 " + lkm1 + "-" + lkm2 + " 路口"); treeView1.Focus(); break; } } }
谢谢观看!