百度地图JSAPI提供两种绘制多折线的方式,一种是已知多折线经纬度坐标串通过AddOverlay接口进行添加;另一种是通过在地图上鼠标单击进行绘制(鼠标绘制工具条库)。目前这两种方式只能绘制多折线,并不能同时绘制线的箭头,以下介绍如何在线的拐点同时绘制箭头,以供参考。最终效果如下:
1. 绘制箭头方法:
上图中,线段AB是通过JSAPI画线方式添加的,只要绘制出CBD就可以实现箭头效果。为了灵活绘制箭头,需要用户自定义箭头的长度(r)和角度(angle)。
实现步骤如下:
变量定义:pixelStart: 线的一端屏幕坐标,pixelEnd:线的箭头端屏幕坐标;r:选取多长距离绘制箭头(单位像素,并不是CB对应的箭头的长度,而是红色线段对应的距离);angle:箭头线(CB或者DB)与AB的夹角。
1) 首先要将AB两点的经纬度坐标转换成屏幕坐标。
2) 然后根据AB两点屏幕坐标以及r长度,计算绿色小绿点的屏幕坐标pixelTem。
3) 然后根据B点、小绿点的屏幕坐标及angle角度,计算出C,D两点的屏幕坐标。
4) 利用map的坐标转换方法,将C,D两点的屏幕坐标转成经纬度表示的坐标。
5) 利用画线方法,绘制CBD多折线。
备注:思路很简单,主要是计算小绿点、C,D的屏幕坐标麻烦。楼主计算这些点的公式均来自与初中数学公式,就不再赘述直接上代码了。
完整代码如下:
<!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:78%;float:left;border-right:2px solid #bcbcbc;}
#r-result{height:100%;width:20%;float:left;}
</style>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=1.4"></script>
<title>折线</title>
</head>
<body>
<div id="allmap"></div>
</body>
</html>
<script type="text/javascript">
var map = new BMap.Map("allmap");
var point = new BMap.Point(116.404, 39.915);
map.centerAndZoom(point, 15);
map.addControl(new BMap.NavigationControl());
map.enableScrollWheelZoom(); var polyline = new BMap.Polyline([
//new BMap.Point(116.399, 39.910),
new BMap.Point(116.405, 39.920),
new BMap.Point(116.425,39.91936),
new BMap.Point(116.415,39.93936),
// new BMap.Point(116.415,39.92936),
], {strokeColor:"blue", strokeWeight:3, strokeOpacity:0.5});
map.addOverlay(polyline);
addArrow(polyline,10,Math.PI/7); function addArrow(polyline,length,angleValue){ //绘制箭头的函数
var linePoint=polyline.getPath();//线的坐标串
var arrowCount=linePoint.length;
for(var i =1;i<arrowCount;i++){ //在拐点处绘制箭头
var pixelStart=map.pointToPixel(linePoint[i-1]);
var pixelEnd=map.pointToPixel(linePoint[i]);
var angle=angleValue;//箭头和主线的夹角
var r=length; // r/Math.sin(angle)代表箭头长度
var delta=0; //主线斜率,垂直时无斜率
var param=0; //代码简洁考虑
var pixelTemX,pixelTemY;//临时点坐标
var pixelX,pixelY,pixelX1,pixelY1;//箭头两个点
if(pixelEnd.x-pixelStart.x==0){ //斜率不存在是时
pixelTemX=pixelEnd.x;
if(pixelEnd.y>pixelStart.y)
{
pixelTemY=pixelEnd.y-r;
}
else
{
pixelTemY=pixelEnd.y+r;
}
//已知直角三角形两个点坐标及其中一个角,求另外一个点坐标算法
pixelX=pixelTemX-r*Math.tan(angle);
pixelX1=pixelTemX+r*Math.tan(angle);
pixelY=pixelY1=pixelTemY;
}
else //斜率存在时
{
delta=(pixelEnd.y-pixelStart.y)/(pixelEnd.x-pixelStart.x);
param=Math.sqrt(delta*delta+1); if((pixelEnd.x-pixelStart.x)<0) //第二、三象限
{
pixelTemX=pixelEnd.x+ r/param;
pixelTemY=pixelEnd.y+delta*r/param;
}
else//第一、四象限
{
pixelTemX=pixelEnd.x- r/param;
pixelTemY=pixelEnd.y-delta*r/param;
}
//已知直角三角形两个点坐标及其中一个角,求另外一个点坐标算法
pixelX=pixelTemX+ Math.tan(angle)*r*delta/param;
pixelY=pixelTemY-Math.tan(angle)*r/param; pixelX1=pixelTemX- Math.tan(angle)*r*delta/param;
pixelY1=pixelTemY+Math.tan(angle)*r/param;
} var pointArrow=map.pixelToPoint(new BMap.Pixel(pixelX,pixelY));
var pointArrow1=map.pixelToPoint(new BMap.Pixel(pixelX1,pixelY1));
var Arrow = new BMap.Polyline([
pointArrow,
linePoint[i],
pointArrow1
], {strokeColor:"blue", strokeWeight:3, strokeOpacity:0.5});
map.addOverlay(Arrow);
}
}
</script>
android里的代码
/**
* 添加方向箭头
*
* @param pts 经纬度列表
* @param length 箭头长度
* @param angleValue 箭头和主线的夹角 度
*/
private void addArrow(List<LatLng> pts,int length,double angleValue)
{
LatLng startLatLng = pts.get(pts.size()-37);
LatLng endLatLng = pts.get(pts.size()-4);
Point screenStart = mBaiduMap.getProjection().toScreenLocation(startLatLng);
Point screenEnd = mBaiduMap.getProjection().toScreenLocation(endLatLng);
System.out.println("addArrow screenStart.x:"+screenStart.x+" screenEnd.y:"+screenEnd.y);
if(null == screenStart || null == screenEnd)
{
return ; }
double angle = angleValue;//angleValue * Math.PI / 180;////箭头和主线的夹角
double delta=0; //主线斜率,垂直时无斜率
double param=0; //代码简洁考虑 , 斜率的平方根
double screenTemX,screenTemY;//临时点坐标
double screenX,screenY,screenX1,screenY1; //箭头两个点 if((screenEnd.x-screenStart.x) == 0) //线路在屏幕上是垂直,斜率不存在是时
{
screenTemX = screenEnd.x;
if(screenEnd.y>screenStart.y)
{
screenTemY = screenEnd.y-length;
}else {
screenTemY = screenEnd.y+length;
}
//已知直角三角形两个点坐标及其中一个角,求另外一个点坐标算法
// screenX = screenTemX-Math.round(length*Math.tan(angle));
// screenX1 = screenTemX+Math.round(length*Math.tan(angle));
screenX = screenTemX-length*Math.tan(angle);
screenX1 = screenTemX+length*Math.tan(angle);
screenY = screenY1 = screenTemY;
}
else //斜率存在时
{
delta = (screenEnd.y-screenStart.y)/(screenEnd.x-screenStart.x);
param = Math.sqrt(delta*delta+1); if((screenEnd.x-screenStart.x)<0)//第二,第三象限
{
screenTemX = screenEnd.x+length/param;
screenTemY = screenEnd.y+delta*length/param;
}else //第一,第四象限
{
screenTemX = screenEnd.x-length/param;
screenTemY = screenEnd.y-delta*length/param;
} //已知直角三角形两个点坐标及其中一个角,求另外一个点坐标算法
// screenX = screenTemX+Math.round(Math.tan(angle)*length*delta/param);
// screenY = screenTemY-Math.round(Math.tan(angle)*length/param);
//
// screenX1 = screenTemX-Math.round(Math.tan(angle)*length*delta/param);
// screenY1 = screenTemY+Math.round(Math.tan(angle)*length/param);
screenX = screenTemX+Math.tan(angle)*length*delta/param;
screenY = screenTemY-Math.tan(angle)*length/param; screenX1 = screenTemX-Math.tan(angle)*length*delta/param;
screenY1 = screenTemY+Math.tan(angle)*length/param; Point pointArrow = new Point(Math.round((float)screenX),Math.round((float)screenY));
Point pointArrow1 = new Point(Math.round((float)screenX1),Math.round((float)screenY1));
// Math.round((float)screenX1),Math.round((float)screenY1) LatLng latArrow = mBaiduMap.getProjection().fromScreenLocation(pointArrow);
LatLng latArrow1 = mBaiduMap.getProjection().fromScreenLocation(pointArrow1); List<LatLng> arrowList = new ArrayList<LatLng>();
arrowList.add(latArrow);
arrowList.add(endLatLng);
arrowList.add(latArrow1); OverlayOptions arrowLine = new PolylineOptions()
.points(arrowList)
.color(0xAAFF0000)
.width(5)
.visible(true); mBaiduMap.addOverlay(arrowLine); }
}
(出处http://blog.csdn.net/baidulbs/article/details/8571961)