如何利用百度地圖JSAPI畫帶箭頭的線?


   百度地圖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)


免責聲明!

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



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