Leaflet使用中經(jīng)驗(yàn)總結(jié)
標(biāo)簽:leaflet
1.Leaflet中使用復(fù)選框控制圖層顯示
? Leaflet本身有圖層控制的支持,但最近用Leaflet做臺風(fēng)的小項(xiàng)目劫侧,其中一個(gè)細(xì)節(jié)是使用復(fù)選框控制圖層顯示與否宠纯,解決方法作如下記錄刃跛。在表格中的"選擇”列是對應(yīng)一個(gè)臺風(fēng)圖層的復(fù)選框俭尖,通過勾選來展示和隱藏本圖層盆昙。Leaflet中的圖層有其所屬的leaflet_id幽勒,是為了保證圖層的唯一性缰泡,但要選中復(fù)選框來操作對應(yīng)的圖層,顯然leaflet_id幫不上什么忙了代嗤。
? 于是棘钞,在繪制圖層時(shí)給圖層綁定一個(gè)自定義的layerId。
var id = 202002;
var lyr_point = L.circle(……);
var lyr_polyline = L.polyline(……);
var lyr = L.featureGroup([lyr_point,lyr_polyline]);
lyr.options.layerId = id; // 給圖層(組)lyr綁定自定義id,在options參數(shù)里添加
? js創(chuàng)建復(fù)選框時(shí)干毅,給每一個(gè)復(fù)選框綁定id宜猜,值即為對應(yīng)臺風(fēng)的id。要展示圖層時(shí)硝逢,查看當(dāng)前選中復(fù)選框是否選中姨拥,若選中則根據(jù)id構(gòu)造url繪制;要隱藏圖層時(shí)渠鸽,遍歷圖層組叫乌,若傳入的id與某一個(gè)圖層的layerId匹配,則隱藏該圖層徽缚。復(fù)選框綁定的函數(shù)框架如下憨奸,這樣就可以實(shí)現(xiàn)使用復(fù)選框控制圖層了。
function showPath(id){
if(document.getElementById(id.toString()).checked){
//這里使用id構(gòu)造url凿试,利用返回的數(shù)據(jù)繪制圖層
}else{
lyrGroup.eachLayer(function (layer){
if(id == layer.options.LayersID){
lyr.removeLayer(layer);
}
}
}
}
[圖片上傳失敗...(image-fac0aa-1594712751210)]
2.臺風(fēng)風(fēng)圈的繪制
? Leaflet中繪制臺風(fēng)風(fēng)圈排宰,網(wǎng)上有 一篇博客 實(shí)現(xiàn)的比較完整,具體思路是擴(kuò)展L.Polygon類那婉,使用SVG的path繪制板甘。但我這里調(diào)用這個(gè)擴(kuò)展類繪制的風(fēng)圈不穩(wěn)定,在地圖縮放详炬、拖動盐类,窗口大小的改變都會是風(fēng)圈圖層消失。在瀏覽器中查看呛谜,發(fā)現(xiàn)上述操作是SVG的path里的d屬性清零了在跳,百思不得其解,于是乎放棄這個(gè)方法呻率,改使用turf.js繪制風(fēng)圈硬毕。
? turf.js是瀏覽器和Node.js環(huán)境下的高級地理空間分析的js庫,里面實(shí)現(xiàn)了很多常見的空間分析礼仗,比如緩沖區(qū)吐咳、點(diǎn)在多邊形內(nèi)等逻悠。我這里用lineArc函數(shù),指定中心點(diǎn)韭脊、半徑童谒、起始和終止角度后,它可以繪制一段圓弧沪羔,注意這里的圓弧是由計(jì)算出來的很多點(diǎn)擬合而成的饥伊,并不是真正的繪制了一條圓弧。其中options參數(shù)中的step默認(rèn)為64蔫饰,如果想要展示效果更順滑一點(diǎn)琅豆,可以選擇擬合點(diǎn)數(shù)。
? 分別指定東北篓吁,東南茫因,西南,西北四個(gè)方向上的半徑長度杖剪,單位默認(rèn)是kilometer冻押,生成四段圓弧,再把四段圓弧的坐標(biāo)都push進(jìn)一個(gè)數(shù)組盛嘿,利用lineString函數(shù)生成線要素洛巢,再利用lineToPolygon函數(shù)轉(zhuǎn)換為多邊形。
? 最后次兆,使用L.geoJSON將風(fēng)圈圖層添加到地圖上稿茉。實(shí)現(xiàn)函數(shù)貼在下方。
// p--中心點(diǎn)(包含四個(gè)方向的半徑),lyr--風(fēng)圈圖層所添加進(jìn)的圖層組
function drawTyphoonCircle(p,lyr){
var center = turf.point([p.longitude, p.latitude]);
var r_ne,r_se,r_sw,r_nw;
if(p.radius7_quad && p.radius7){
r_ne = p.radius7_quad.ne;
r_se = p.radius7_quad.se;
r_sw = p.radius7_quad.sw;
r_nw = p.radius7_quad.nw;
}else{
return;
}
var options = {number:2048};
var arc_ne = turf.lineArc(center, r_ne, 0, 89.9,options);
var arc_se = turf.lineArc(center, r_se, 90, 179.9,options);
var arc_sw = turf.lineArc(center, r_sw, 180, 269.9,options);
var arc_nw = turf.lineArc(center, r_nw, 270, 360.1,options);
var arcs = [];
arcs.push(arc_ne,arc_se,arc_sw,arc_nw);
var myStyle = {
"color": "#ccffcc",
"weight": 2,
"fillColor":"#ccffcc"
};
var typhoonCircleCoords = [];
for(var i=0;i<arcs.length;i++){
var rawCoords1 = arcs[i].geometry.coordinates;
for(var j=0;j<rawCoords1.length;j++){
typhoonCircleCoords.push(rawCoords1[j]);
}
}
var lineAll = turf.lineString(typhoonCircleCoords);
var typhoonCirclePolygon = turf.lineToPolygon(lineAll);
L.geoJSON(typhoonCirclePolygon,{style:myStyle}).addTo(lyr);
}
3.給表格添加滾動條类垦,設(shè)置后無效
overflow-y設(shè)置為true后狈邑,要設(shè)置height為一個(gè)固定的值城须,比如600px蚤认。
4.Leaflet中加載Mapbox自定義地圖
使用L.tileLayer創(chuàng)建,url template中的username是Mapbox的注冊賬戶的用戶名糕伐。在https://studio.mapbox.com/中自定義圖層的分享按鈕處點(diǎn)擊砰琢,即可看到style_id和Access Token。
var mymap = L.map('map').setView([20.557212,126.402354],3.5);
L.tileLayer('https://api.mapbox.com/styles/v1/{username}/{style_id}/tiles/512/{z}/{x}/{y}?access_token={accessToken}',{
username:'whitedreamer',
style_id:'cjn64ahui0ycg2rq72fer5a3r',
accessToken:'pk.eyJ1Ijoid2hpdGVkcmVhbWVyIiwiYSI6ImNqbjN4azFjcDAwbG0zcG52aGc3M2x0M2sifQ.CYsl1oXDVr1PWgx4z6lSeg'
}).addTo(mymap);
5.單擊表格行等同于單擊行內(nèi)的復(fù)選框良瞧,選中圖層
這個(gè)功能是問題1的改進(jìn)版陪汽,需要修改原有的代碼邏輯。首先褥蚯,刪除復(fù)選框的onclick綁定的事件挚冤,然后改寫showPath函數(shù):根據(jù)圖層id(等同于checkbox的id)繪制臺風(fēng)路徑,增加hidePath函數(shù):根據(jù)圖層id隱藏臺風(fēng)路徑赞庶;最后训挡,編寫selectARow函數(shù)澳骤,獲取所點(diǎn)擊表格行中的復(fù)選框id,根據(jù)id判斷圖層是否已繪制澜薄,若未繪制則繪制該圖層为肮,若已繪制則取消繪制。
注意:selectARow函數(shù)根據(jù)id判斷復(fù)選框是否被選中來判斷圖層是否已繪制肤京,存在邏輯矛盾颊艳,因?yàn)辄c(diǎn)擊復(fù)選框是點(diǎn)擊就繪制,取消就取消繪制忘分;而點(diǎn)擊表格行是若未選中則選中后繪制棋枕,若選中了則取消選中然后取消繪制。這兩個(gè)邏輯相反妒峦,無法調(diào)和戒悠,故采取上述邏輯。
function showPath(id){
lyr_num += 1;//lyr_num是圖層數(shù)量
if(lyr_num > 4){
alert('Layers More Than 4.');
}
var url = 'https://www.readearth.com/typhoon/'+id.toString().slice(0,4)+'/'+id+'.json';
draw(url,id);
$('.badge')[0].innerHTML=lyr_num;//bootstrap徽標(biāo)舟山,顯示在按鈕上绸狐,展示當(dāng)前選中的圖層數(shù)量
ids.push(id);
}
function hidePath(id){
lyr.eachLayer(function (layer){
if(id == layer.options.LayersID){
lyr.removeLayer(layer);
lyr_num -= 1;
$('.badge')[0].innerHTML=lyr_num;//更新當(dāng)前顯示的圖層數(shù)量
}
});
ids.forEach(function(item, index) {
if(item == id) {
ids.splice(index, 1);//刪除id數(shù)組中的對應(yīng)項(xiàng)
}
});
}
function selectARow(){
$('.table').on('click','tr',function(){
var td_checkbox = $(this)[0].children[3];//獲取checkbox所在td
var checkbox = td_checkbox.children[0];//獲取checkox
var id = parseInt(checkbox.id);//獲取checkbox的id
// flag標(biāo)志行對應(yīng)的圖層是否已繪制,若已繪制則移除累盗,若未繪制則繪制寒矿,默認(rèn)未繪制
var layers = lyr.getLayers();
var flag = 0;
if(layers.length){
lyr.eachLayer(function(layer){
if(id == layer.options.LayersID){
flag = 1;
}
})
}
if(flag){
checkbox.checked = false;
hidePath(id);
}else{
checkbox.checked = true;
showPath(id);
}
})
}
6.一個(gè)div浮在一個(gè)div之上
假設(shè)div1在底下,div2浮在上方若债,則css應(yīng)該這么寫符相。注意:div1與div2之間是平行關(guān)系,不是嵌套關(guān)系蠢琳,但div1定義要在div2之上啊终。
#div1{
position:absolute;
}
#div2{
positon:relative;
z-index:1/*div2的z-index大于div1的z-index即可,默認(rèn)div1的z-index為0*/
}
7.Echarts繪制圖表的依賴
從Echarts官網(wǎng)下載的官方案例會引入很多文件傲须,一般的圖表蓝牲,像餅圖、條形圖泰讽、折線圖等等例衍,只需要引入一個(gè)文件,即:
<!-- 引入echarts.js -->
<script type='text/javascript' src='https://cdn.bootcss.com/echarts/4.2.1-rc1/echarts.min.js'></script>
推薦下載下來本地引用已卸,在線引用速度略慢佛玄。