在高德地圖上用svg.js繪制簡單圖形


這段時間做的一個項目,需要在地圖上繪制簡單的圖形。在學習高德地圖JS API的過程中,發現高德地圖提供的點、線等API並不能滿足我的需求,還好它開放了自定義圖層CustomLayer,官方說自定義圖層支持canvassvg、甚至dom,這里我用的是svg,多說無益,上代碼。

一、高德地圖

以下的步驟在官方文檔中都有,而且官方文檔比較齊全。

首先需要去高德API官網申請自己的key,此步略過。

拿到key后在頁面中引入地圖所用的js

<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=申請的key"></script> 

准備一個放置地圖的容器,指定特定的高度,寬度。我是將容器高度寬度全部設置為100%。

<div id="container"></div>
html, body, #container {
    margin: 0;
    padding: 0;
    width: 100%;
    height: 100%;
}

最后一步,在js中指定容器,加載地圖,然后就可以在頁面中看到你的地圖了。

// 第一個參數是容器名稱,第二個參數可以按自己需求隨意配置。
var map = new AMap.Map('container', {
    zoom: 15, // 縮放等級
    center: [115.49481017, 38.88656455], // 中心點
    features: ['bg', 'road', 'building'] // 設置地圖中顯示的元素, 'bg'(地圖背景)、'point'(POI點)、'road'(道路)、'building'(建築物)
});

二、自定義圖層

下面開始編寫自定義圖層,除過地圖所用的js文件,我還用到了jquery

首先地圖有一部分是異步加載的,所以需要在地圖加載完成后,再去編寫自定義圖層,否則容易報錯,而地圖也給我們提供了complete事件。

map.on('complete', function(){
    // TODO 編寫自定義圖層
})

然后聲明svg,創建圖層

svg和地圖類似,也需要先聲明一個容器,此容器和地圖等寬等高

var svg = $('<svg id="drawing" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" ></svg>')[0];
#drawing {
    margin: 0;
    padding: 0;
    width: 100%;
    height: 100%;
}

創建圖層

// 第一個參數傳入我們創建的svg對象,第二個參數為圖層配置,可以根據自己需求進行配置
var customLayer = new AMap.CustomLayer(svg, {
    zIndex: 100,
    zooms: [3, 18],
    alwaysRender: true
});
map.add(customLayer); // 要把圖層添加到地圖中

二、在圖層中畫自己喜歡的圖形。

為了簡化代碼,項目中采用了svg.js

// 調用svg.js提供的SVG函數,傳入我們創建的svg對象,創建所需要的draw對象。
var draw = SVG(svg);

現在我們開始在地圖上畫線。

我們規定在地圖上單擊即為線的起點,再進行單擊即為線的終點。

首先為地圖注冊單機事件

var isDraw = false; // 用來判斷是開始畫線還是結束畫線。
var startPix; // 用來存儲起點
map.on('click', function(ev){
    isDraw = !isDraw;
    if(isDraw) {
        // isDraw為true就標明起點
        startPos = ev.pixel; 
    }else{
        // isDraw為false就畫線。 
    }
})

然后編寫畫線函數

function drawLine(start, end) {
    var lineWth = 3;
    var lineColor = 'blue';
    var x = start.x;
    var y = start.y;
    var x1 = end.x;
    var y1 = end.y;
    line = draw.line(x, y, x1, y1).stroke({ color: lineColor, width: lineWth });
    return line; 
}

然后完善地圖單擊事件

map.on('click', function(ev){
    isDraw = !isDraw;
    if(isDraw){
        // isDraw為true就標明起點
        startPix = ev.pixel;
    }else{
        // isDraw為false就畫線。 
        var endPix = ev.pixel;
        drawLine(startPix, endPix);
    }
})

至此就可以在地圖上簡單的畫直線了。

但是當我們單擊地圖開始畫線時,此時地圖上沒有任何東西,再點擊地圖時,線突然的出現,這樣顯得比較突兀。現在我們需要修改成,當開始畫線時,線跟隨鼠標移動而移動,再點擊地圖時,結束畫線。

我們需要先注冊地圖mousemove事件

map.on('mousemove', function (ev) {
    if(isDraw) {
        drawLine(startPix, ev.pixel)
    }
});

注冊完鼠標移動時間后,線是可以跟隨鼠標移動了,但是現在出現了一個小問題:

所有畫的線都留下了來了,這時我們需要將多余的線去掉。

在鼠標移動時 去掉多余的線,這里需要用到draw對象的group功能。

var lineGroup; // 聲明一個對象 存儲line。
map.on('click', function(ev){
    isDraw = !isDraw;
    if(isDraw){
        // isDraw為true就標明起點
        startPix = ev.pixel;
        lineGroup = draw.group(); // 開始畫線時創建一個group。
    }else{
        // isDraw為false就畫線。 
        var endPix = ev.pixel;
        drawLine(startPix, endPix);
    }
});
map.on('mousemove', function(ev){
    if(isDraw) {
        lineGroup.clear(); // 在鼠標移動時先將group清空。
        var line = drawLine(startPix, ev.pixel);
        lineGroup.add(line);// 將新線添加到group中。
    }
})

至此,我們完成了讓線跟隨鼠標移動。

三、地圖重繪時,讓畫的線隨實際經緯度坐標重繪。

我們現在所畫的線,在拖動、放大、縮小地圖時,是不會跟隨地圖變化而變化的。

首先需要創建一個數組用來存儲坐標點,一個對象用來存儲起點坐標。

var positions = [];
var startPos;

然后開始畫線記錄起始點經緯度坐標,結束畫線時將兩點坐標存入數組。

map.on('click', function(ev){
    isDraw = !isDraw;
    if(isDraw){
        // isDraw為true就標明起點
        startPos = ev.lnglat; /*手動高亮*/
        startPix = ev.pixel;
        lineGroup = draw.group();
    }else{
        // isDraw為false就畫線。 
        var endPix = ev.pixel;
        drawLine(startPix, endPix);
        positions.push({ /*手動高亮*/
            start: startPos,
            end: ev.lnglat
        })
    }
});

最后注冊的是自定義層的重繪事件。

customLayer.render = onRender;
function onRender() {
    draw.clear(); // 先將畫板清空
    for(var i = 0;i < positions.length;i++){
        // 需要將經緯度坐標轉換為容器內坐標,lngLatToContainer是高德提供的轉換方法
        var startPixCon = map.lngLatToContainer(positions[i].start);
        var endPixCon = map.lngLatToContainer(positions[i].end);
        drawLine(startPixCon, endPixCon);
    }
}

現在我們畫的線就可以隨地圖變化而變化了。


免責聲明!

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



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