leaflet_常用方法
程序员文章站
2022-06-11 16:12:43
...
文章目录
0. note
点 116.519623 39.871277
线 116.341782 39.91316 ,116.431732 39.944753
面 116.273804 39.931591,116.344528 39.939225,116.328049 39.898148,116.258354 39.906049
经lng 纬lat度
1. 度转度°分′秒″
function ToDegrees(val) { //156.3564
if (typeof (val) == "undefined" || val == "") {
return "";
}
var i = val.indexOf('.');
var strDu = i < 0 ? val : val.substring(0, i);//获取度
var strFen = 0;
var strMiao = 0;
if (i > 0) {
var strFen = "0" + val.substring(i);
strFen = strFen * 60 + "";
i = strFen.indexOf('.');
if (i > 0) {
strMiao = "0" + strFen.substring(i);
strFen = strFen.substring(0, i);//获取分
strMiao = strMiao * 60 + "";
i = strMiao.indexOf('.');
strMiao = strMiao.substring(0, i + 4);//取到小数点后面三位
strMiao = parseFloat(strMiao).toFixed(2);//精确小数点后面两位
}
}
return strDu + "," + strFen + "," + strMiao;
}
2. 度°分′秒″转度
function ToDigital(strDu, strFen, strMiao, len) {
len = (len > 6 || typeof (len) == "undefined") ? 6 : len;//精确到小数点后最多六位
strDu = (typeof (strDu) == "undefined" || strDu == "") ? 0 : parseFloat(strDu);
strFen = (typeof (strFen) == "undefined" || strFen == "") ? 0 : parseFloat(strFen) / 60;
strMiao = (typeof (strMiao) == "undefined" || strMiao == "") ? 0 : parseFloat(strMiao) / 3600;
var digital = strDu + strFen + strMiao;
if (digital == 0) {
return "";
} else {
return digital.toFixed(len);
}
}
3. line.js 画线 + 动画
import {
path
} from ‘./line.js’;
let ary = [];
for (let i = 0; i < this.route_list.length; i++) {
let lng = parseFloat(this.route_list[i].LNG);
let lat = parseFloat(this.route_list[i].LAT);
let color = this.route_list[i].LEVEL_COLOR;
let ary_0 = [lat, lng, color];
ary.push(ary_0);
}
let newarr = [];
newarr.push(ary);
let props = {};
props = {
data: newarr,
map: this.myMap,
XCSJ: "2019-07-03"
}
path.initpath(props);
var path = {
name: "人员路径",
layerGroups: [],
TotalLine: 0, //轨迹总数
TotalPoint: 0, //轨迹中点的总数
lineIndex: 0, //当前轨迹序号
PointList: [], //每条轨迹包含点的个数
linePathColor: '#bb343b', //路径颜色
// 初始化
initpath(props) {
console.log(props);
this.routeCoords = props.data;
this.myMap = props.map;
this.initLayer(props.XCSJ);
this.setStartIcon(this.routeCoords[0][0]);
this.setEndIcon(this.routeCoords[0][0]);
this.addAllLine();
this.TotalLine = this.routeCoords.length;
this.TotalPoint = 0; //轨迹中点的总数
this.pointIndex = 0;
this.lineIndex = 0; //当前轨迹序号
this.PointList = [];
this.routeCoords.forEach((v, index) => {
this.TotalPoint = this.TotalPoint + v.length;
this.PointList.push(v.length);
this.addPatrol(index);
});
// console.log(this.PointList);
},
//初始化图层
initLayer() {
if (this.layerGroups.length > 0) {
this.layerGroups.forEach(da => {
da.clearLayers();
});
} else {
this.layerGroup = L.layerGroup().addTo(this.myMap);
this.layerGroups.push(this.layerGroup);
}
},
setStartIcon(val) { //设置起点
// let markerS = L.circle([val[0], val[1]], {
// color: val[2],
// fillColor: val[2],
// fillOpacity: 1,
// radius: 12000, //半径
// });
// this.layerGroup.addLayer(markerS);
},
setEndIcon(val) { //设置终点
let myIcon = L.divIcon({
html: `<img style="" src="static/image/typhoon.png"></img> `,
className: 'windy_direction_rotate',
})
let markerS = L.marker([val[0], val[1]], {
icon: myIcon
});
// markerS.on('click', () => {
// typhoon_monitor_show_detail(this.routeCoords[0].length - 1);
// });
this.layerGroup.addLayer(markerS);
this.nowMarker = markerS;
},
addAllLine() { //重置地图 使轨迹位于屏幕中部
if (this.polyline) {
this.polyline.remove();
}
this.polyline = L.polyline(this.routeCoords, {
color: '#bb343b'
});
this.myMap.fitBounds(this.polyline.getBounds(), {
paddingTopLeft: [100, 100],
paddingBottomRight: [200, 100],
})
},
addPatrol(index) { //添加轨迹
// 线的起始点
let start_lng = this.routeCoords[index][0][1];
let start_lat = this.routeCoords[index][0][0];
let start_color = this.routeCoords[index][0][2];
let arr = [start_lat, start_lng];
let linePathName = 'linePath' + index;
this[linePathName] = L.polyline([arr], {
color: this.linePathColor
});
let myIcon = L.divIcon({
html: `<div style="width:10px;height:10px;background:${start_color};border-radius:50%;font-weight:600;"></div> `,
iconAnchor: [5, 5],
className: ''
})
let markerS = L.marker([start_lat, start_lng], {
icon: myIcon,
});
// 起始点 marker
// let markerS = L.circle([start_lat, start_lng], {
// color: start_color,
// fillColor: start_color,
// fillOpacity: 1,
// radius: 12000, //半径
// offset: [0, 0],
// });
markerS.on('click', () => {
typhoon_monitor_show_detail(0)
});
this.layerGroup.addLayer(this[linePathName]);
this.layerGroup.addLayer(markerS);
if (index == this.TotalLine - 1) {
this.startAnimation();
}
},
//开始移动轨迹
startAnimation() {
let goto = true;
while (this.isPath()) {
this.pointIndex++;
if (this.pointIndex = this.PointList[this.lineIndex] - 1) {
goto = false;
break;
}
}
if (goto) {
this.nowTime = new Date().getTime();
this.moveFeature();
}
},
//计算两个轨迹点之间的距离 如果距离过大 不移动 跳过该点
isPath() {
let A = this.routeCoords[this.lineIndex][this.pointIndex];
let B = this.routeCoords[this.lineIndex][this.pointIndex + 1];
var lat = [A[0], B[0]]
var lng = [A[1], B[1]]
var R = 6378137;
var dLat = (lat[1] - lat[0]) * Math.PI / 180;
var dLng = (lng[1] - lng[0]) * Math.PI / 180;
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(lat[0] * Math.PI / 180) * Math.cos(lat[1] * Math.PI / 180) * Math.sin(dLng / 2) * Math.sin(dLng / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
return false;
},
//移动轨迹
moveFeature() {
if (this.routeCoords.length > 0) { //几条线 []
let timestamp = new Date().getTime();
let elapsedTime = timestamp - this.nowTime;
let duration = elapsedTime / 100; //22毫秒
if (duration < 1 && this.TotalPoint > this.pointIndex) {
// let offsetX = (this.routeCoords[this.lineIndex][this.pointIndex + 1][0] - this.routeCoords[this.lineIndex][this.pointIndex][0]) * duration;
// let offsetY = (this.routeCoords[this.lineIndex][this.pointIndex + 1][1] - this.routeCoords[this.lineIndex][this.pointIndex][1]) * duration;
// let position = [this.routeCoords[this.lineIndex][this.pointIndex][0] + offsetX, this.routeCoords[this.lineIndex][this.pointIndex][1] + offsetY];
// this.nowMarker.setLatLng(position);
// this['linePath' + this.lineIndex].addLatLng(position);
this['linePath' + this.lineIndex].addLatLng(this.routeCoords[this.lineIndex][this.pointIndex + 1]);
requestAnimationFrame(this.moveFeatureSelf(this));
} else {
this.stopAnimation();
}
}
},
moveFeatureSelf(self) {
return self.moveFeature.bind(self)
},
stopAnimation() { //停止移动轨迹
let num = this.pointIndex + 1;
let val = this.routeCoords[0][this.pointIndex + 1];
let myIcon = L.divIcon({
html: `<div style="width:10px;height:10px;background:${val[2]};border-radius:50%;font-weight:600;"></div> `,
iconAnchor: [5, 5],
className: 'stopAnimation'
})
let markerS = L.marker([val[0], val[1]], {
icon: myIcon
});
// let markerS = L.circle([val[0], val[1]], {
// color: val[2],
// fillColor: val[2],
// fillOpacity: 1,
// radius: 12000 //半径
// });
markerS.on('click', () => {
typhoon_monitor_show_detail(num)
});
this.layerGroup.addLayer(markerS);
this.pointIndex++;
// 画完一条线 开始画另一条线
if ((this.pointIndex > this.PointList[this.lineIndex] - 2) &&
this.lineIndex < this.TotalLine - 1) {
this.lineIndex++;
this.pointIndex = 0;
}
if (this.pointIndex < this.PointList[this.lineIndex] - 1) { //更新终点位置
this.nowMarker.setLatLng(this.routeCoords[this.lineIndex][this.pointIndex + 1]);
this.startAnimation();
}
},
}
export {
path
}
4. 画四个半径不同的圆形
由四个扇形构成 200,200,200,200
draw_arcs(item, LAT, LNG, type) {
let radius_list = Array.from(item.split(","));
let arc_list = [{
from: 0,
to: 90
}, {
from: 90,
to: 180
}, {
from: 180,
to: 270
}, {
from: 270,
to: 360
}];
let lng_lat = {
lon: LNG,
lat: LAT,
}
this.typhoon_range = [];
arc_list.map((item, index) => {
let points = this.getPoints([LAT, LNG], parseInt(radius_list[index]) / 200, item.from, item.to, 500);
this.typhoon_range = this.typhoon_range.concat(points);
})
let typhoon_range_item = L.polygon(this.typhoon_range, {
color: type == 7 ? "rgb(255, 248, 0)" : "rgb(247, 122, 6)",
fillColor: type == 7 ? "rgb(210, 205, 45)" : "rgb(192, 121, 55)",
fillOpacity: 0.2,
}).addTo(this.typhoon_range_group);
}
画扇形
getPoints(center, radius, startAngle, endAngle, pointNum) {
/**
*
* @param center 中心点 数组
* @param radius 半径 km
* @param startAngle 起始角度
* @param endAngle 终止角度
* @param pointNum 圆弧上点的个数
*/
var sin;
var cos;
var x;
var y;
var angle;
var points = new Array();
for (var i = 0; i <= pointNum; i++) {
angle = startAngle + (endAngle - startAngle) * i / pointNum;
sin = Math.sin(angle * Math.PI / 180);
cos = Math.cos(angle * Math.PI / 180);
y = parseFloat(center[0]) + parseFloat(radius * cos);
x = parseFloat(center[1]) + parseFloat(radius * sin);
points[i] = [y, x];
}
// points.push(center); //扇形
return points;
},
5. 已知一个经纬度,距离,仰角->另一个经纬度
import {
get_another_lng_lat
} from ‘./get_another_lng_lat.js’;
let arc_list = [{
from: 0,
to: 90
}, {
from: 90,
to: 180
}, {
from: 180,
to: 270
}, {
from: 270,
to: 360
}];
let circle_list = [{
radius: 5000,
color: 'red',
rotate: 120,
num: 0,
}, {
radius: 4000,
color: 'green',
rotate: 160,
num: 1,
}, {
radius: 3000,
color: 'blue',
rotate: 180,
num: 2,
}, {
radius: 3000,
color: 'pink',
rotate: 90,
num: 2,
}];
let lng_lat = {
lng: this.initMap.lng,
lat: this.initMap.lat,
}
arc_list.map((item, index) => {
let points = this.getPoints([this.initMap.lat, this.initMap.lng], circle_list[index].radius / 100000, item.from, item.to, 500);
points[points.length] = points[0];
L.polygon(points, {
color: circle_list[index].color
}).addTo(this.myMap);
})
circle_list.map((item) => {
L.circle([this.initMap.lat, this.initMap.lng], { // 圆形 LatLng
color: item.color,
fillColor: '#ccc',
fillOpacity: 0,
radius: item.radius //半径
}).addTo(this.myMap);
L.polygon([ // 多边形 LatLng
[this.initMap.lat, this.initMap.lng],
[get_another_lng_lat.destinationVincenty(lng_lat, item.rotate, item.radius).lat,
get_another_lng_lat.destinationVincenty(lng_lat, item.rotate, item.radius).lng
],
], {
color: item.color
}).addTo(this.myMap);
let myIcon = L.divIcon({
html: `<div style="position:relative;top:20px;width:100px;font-weight:600;">${item.radius}米,${item.num}次</div> `,
iconAnchor: [20, 20],
iconSize: [40, 40],
className: 'higtIcon'
})
L.marker([get_another_lng_lat.destinationVincenty(lng_lat, item.rotate, item.radius).lat,
get_another_lng_lat.destinationVincenty(lng_lat, item.rotate, item.radius).lng
], {
icon: myIcon
}).addTo(this.myMap);
})
var get_another_lng_lat = {
VincentyConstants: {
a: 6378137,
b: 6356752.3142,
f: 1 / 298.257223563
},
/**
*Calculate destination point given start point lat/long (numeric degrees),
* bearing (numeric degrees) & distance (in m).
*/
destinationVincenty: function(lonlat, brng, dist) {
var u = this;
var ct = u.VincentyConstants;
var a = ct.a,
b = ct.b,
f = ct.f;
var lon1 = lonlat.lon;
var lat1 = lonlat.lat;
var s = dist;
var alpha1 = u.rad(brng);
var sinAlpha1 = Math.sin(alpha1);
var cosAlpha1 = Math.cos(alpha1);
var tanU1 = (1 - f) * Math.tan(u.rad(lat1));
var cosU1 = 1 / Math.sqrt((1 + tanU1 * tanU1)),
sinU1 = tanU1 * cosU1;
var sigma1 = Math.atan2(tanU1, cosAlpha1);
var sinAlpha = cosU1 * sinAlpha1;
var cosSqAlpha = 1 - sinAlpha * sinAlpha;
var uSq = cosSqAlpha * (a * a - b * b) / (b * b);
var A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
var B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
var sigma = s / (b * A),
sigmaP = 2 * Math.PI;
while (Math.abs(sigma - sigmaP) > 1e-12) {
var cos2SigmaM = Math.cos(2 * sigma1 + sigma);
var sinSigma = Math.sin(sigma);
var cosSigma = Math.cos(sigma);
var deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -
B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));
sigmaP = sigma;
sigma = s / (b * A) + deltaSigma;
}
var tmp = sinU1 * sinSigma - cosU1 * cosSigma * cosAlpha1;
var lat2 = Math.atan2(sinU1 * cosSigma + cosU1 * sinSigma * cosAlpha1,
(1 - f) * Math.sqrt(sinAlpha * sinAlpha + tmp * tmp));
var lambda = Math.atan2(sinSigma * sinAlpha1, cosU1 * cosSigma - sinU1 * sinSigma * cosAlpha1);
var C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
var L = lambda - (1 - C) * f * sinAlpha *
(sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));
var revAz = Math.atan2(sinAlpha, -tmp); // final bearing
// return new OpenLayers.LonLat(lon1 + u.deg(L), u.deg(lat2));
// console.log(lon1 + u.deg(L), u.deg(lat2));
return {
lng: parseFloat(lon1) + parseFloat(u.deg(L)),
lat: parseFloat(u.deg(lat2))
}
},
/**
* 度换成弧度
* @param {Float} d 度
* @return {[Float} 弧度
*/
rad: function(d) {
return d * Math.PI / 180.0;
},
/**
* 弧度换成度
* @param {Float} x 弧度
* @return {Float} 度
*/
deg: function(x) {
return x * 180 / Math.PI;
}
}
export {
get_another_lng_lat
}
6.地图联动
this.mapImgInit.map.on('mouseover', e => {
this.mapImgActiveNum = 0;
});
this.mapImgCollect.map.on('mouseover', e => {
this.mapImgActiveNum = 1;
});
this.mapImgInit.map.on("moveend", ev => {
if (this.mapImgActiveNum === 0) {
let obj = this.mapImgInit.map.getBounds();
let imageBounds = [[obj._northEast.lat, obj._northEast.lng], [obj._southWest.lat, obj._southWest.lng]];
this.mapImgCollect.map.fitBounds([imageBounds]);
}
});
this.mapImgCollect.map.on("moveend", ev => {
if (this.mapImgActiveNum === 1) {
let obj = this.mapImgCollect.map.getBounds();
let imageBounds = [[obj._northEast.lat, obj._northEast.lng], [obj._southWest.lat, obj._southWest.lng]];
this.mapImgInit.map.fitBounds([imageBounds]);
this.mapImgInit.isActive = false;
}
});
7. geo_json_data
import * as map_geojson_data from ‘…/…/…/…/static/js/map/sample-geojson.js’
let greenIcon = L.icon({ //坐标图
iconUrl: '../../../../static/img/market/marker-icon.png', //图标地址
iconSize: [25, 41], // 图标宽高
popupAnchor: [-0, -20] // 弹出框弹出位置,相对于图标锚点
});
let coorsLayer = L.geoJSON(map_geojson_data.coorsField, { //小人
pointToLayer: (feature, latlng) => {
return L.marker(latlng, {
icon: greenIcon
}).bindPopup(feature.properties.popupContent);
},
}).addTo(this.mymap);
L.geoJSON([map_geojson_data.bicycleRental, map_geojson_data.campus], { //点
style: function(feature) {
return feature.properties && feature.properties.style;
},
onEachFeature: this.onEachFeature,
pointToLayer: function(feature, latlng) {
return L.circleMarker(latlng, {
radius: 8,
fillColor: "darkgreen",
color: "black",
weight: 1,
opacity: 1,
fillOpacity: 0.8
});
}
}).addTo(this.mymap);
L.geoJSON(map_geojson_data.freeBus, { //线
filter: function(feature, layer) {
if (feature.properties) {
// If the property "underConstruction" exists and is true, return false (don't render features under construction)
return feature.properties.underConstruction !== undefined ? !feature.properties.underConstruction : true;
}
return false;
},
style: function(feature) {
switch (feature.properties.party) {
case 'Republican':
return {
color: "#ff0000"
};
case 'Democrat':
return {
color: "#0000ff"
};
case 'Democrat_1':
return {
color: "lightblue"
};
}
},
onEachFeature: this.onEachFeature
}).addTo(this.mymap);
onEachFeature(feature, layer) { // 弹出框
let popupContent = "<p>我来自GeoJSON的" +
feature.geometry.type + ", 但是我现在是个矢量元素</p>";
if (feature.properties && feature.properties.popupContent) {
popupContent += feature.properties.popupContent;
}
layer.bindPopup(popupContent);
}
8. 定位
8.1 天地图
http://api.tianditu.gov.cn/geocoder?
postStr={%27lon%27:116.37304,%27lat%27:39.92594,%27ver%27:1}&
type=geocode&tk=c32c9da708e8fd5117a5af5cf71f58ed
8.2 百度地图
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
body,
html,
#allmap {
width: 100%;
height: 100%;
overflow: hidden;
margin: 0;
font-family: "微软雅黑";
}
</style>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=NCF1cHxumgwMdr12FRWhVSdY5yhfzR0f"></script>
<title>浏览器定位</title>
</head>
<body>
<div id="allmap"></div>
</body>
</html>
9. 加载矢量瓦片地图 错位
切换矢量瓦片地图
marker点 marker标题 和矢量瓦片地图错误
解决办法 将瓦片地图放到 多个图层组