一、封装leafletMap
javascript
import "leaflet.markercluster";
class LeafletMap {
constructor() {
const a = this;
a.config = {
domId: "container",
center: [33.25, 113.52],
zoom: 8,
zoomSnap: 8.5, //地图缩放级别,支持小数,但会影响地图缩放
zoomControl: false, //禁止缩放
touchZoom: false, //禁止触摸
scrollWheelZoom: false, //禁止鼠标滚轮
dragging: false, //禁止拖拽
};
}
init(config) {
const a = this;
a.config = { ...a.config, ...config,
renderer: L.canvas() // 或者 L.svg()
};
a.map = L.map(a.config.domId, a.config);
return a.map;
}
// 高德离线图层
addGDLayers(url) {
const a = this;
if (!configItem.tmsLayer) {
L.tileLayer(
"http://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}" //在线高德地图
// "http://webst02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8" //在线高德卫星图
).addTo(a.map);
} else {
L.tileLayer(
configItem.tmsLayer , {
/*minZoom: 1,
maxZoom: 14,*/
}
).addTo(a.map);
}
}
// 百度离线图层
addBDLayers(url) {
const a = this;
L.tileLayer(
url || "http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" //在线百度地图
).addTo(a.map);
}
//标准tms图层
addTMSLayers(url, config = {}) {
const a = this;
const CRS_900913 = new L.Proj.CRS(
"EPSG:3395",
"+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs",
{
resolutions: [
156543.032, 78271.516, 39135.758, 19567.879, 9783.9395, 4891.96975,
2445.984875, 1222.9924375, 611.49621875, 305.748109375, 152.874054688,
76.437027344, 38.218513672, 19.109256836, 9.554628418, 4.777314209,
2.388657104, 1.194328552, 0.597164276, 0.298582138, 0.149291069,
0.074645535,
] /*(function () {
var level = 19;
var res = [];
res[0] = Math.pow(2, 18);
for (var i = 1; i < level; i++) {
res[i] = Math.pow(2, 18 - i);
}
console.log(res);
return res;
})()*/,
// origin: [0, 0],
// bounds: L.bounds([20037508.342789244, 0], [0, 20037508.342789244]),
origin: [7340032.00000000372529, -0.00000003068298],
bounds: L.bounds(
[7340032.00000000372529, -0.00000003068298],
[141.291239704979603, 7340032.089508121833205]
),
}
);
config.crs = CRS_900913;
console.log(url);
L.tileLayer(url, config).addTo(a.map);
}
//绘制行政边界(geojson)
addBounds(response, myStyle) {
const a = this;
!myStyle && (myStyle = { color: "#ff7800" });
// Add to layer
var layer = L.geoJSON(response, {
style: myStyle,
}).addTo(a.map);
return layer;
}
// 矢量图层(折线)
addPolylineLayers(latlngs, color, className = "") {
const a = this;
!latlngs &&
(latlngs = [
[45.51, -122.68],
[37.77, -122.43],
[34.04, -118.2],
]);
var polyline = L.polyline(latlngs, {
color: color || "red",
className: className, //类名
weight: 2, //线条宽度
}).addTo(a.map);
//将地图放大到折线
a.map.fitBounds(polyline.getBounds());
}
// 矢量图层(圆)
addCircleLayers(latins, className = "") {
const a = this;
latins = [33.25, 113.52];
L.circle(latins, {
radius: 200,
fillColor: "red", //填充色
fillOpacity: 0.5, //填充透明度 默认0.2
color: "yellow", //描边色
className: className, //类名
}).addTo(a.map);
}
//矢量图层(小图标)
addIconLayers(latlng, config = {}, data, className = "", callback) {
const a = this;
!latlng && (latlng = [33.5, 113.5]);
var obj = {
iconUrl: "../../assets/images/vertices.png",
iconSize: [30, 30],
// iconAnchor: [22, 94], //图标尖端坐标
// popupAnchor: [-3, -76], //弹出窗口"打开"的点相对于图标锚点的坐标
// shadowUrl: "my-icon-shadow.png", //阴影图像
// shadowSize: [68, 95], //阴影图像的大小
// shadowAnchor: [22, 94], //阴影"尖端"的坐标
className: className,
data: data,
};
obj = { ...obj, ...config };
var myIcon = L.icon(obj);
let marker = L.marker(latlng, { icon: myIcon }).on("click", function (e) {
callback(e);
}).addTo(a.map)
return marker;
// L.marker(latlng).addTo(a.map); //标记点
}
//矢量图层聚合
addClusterLayer() {
const a = this;
const markerClusterLayer = L.markerClusterGroup({
showCoverageOnHover: false, // 为true时,当鼠标悬停在点上时,它会显示它聚合的边界
zoomToBoundsOnClick: true, // 为true时,当鼠标点击某个点时,会缩放到它的边界范围
chunkedLoading: true,
maxClusterRadius: 50, // 聚类从中心标记覆盖的最大半径(以像素为单位),默认值 80
// disableClusteringAtZoom: 10 // 在缩放级别10及以下不进行聚合
}).addTo(a.map);
return markerClusterLayer;
}
//矢量图层(文本)同上,可以canvas绘制
addTextLayer(latlng, text, className = "my-div-icon", callback) {
const a = this;
!latlng && (latlng = [33.5, 113.5]);
// 创建自定义图标并添加文本
var customIcon = L.divIcon({className, html: '<span>'+text+'</span>'});
var marker = L.marker(latlng, {className,icon: customIcon})//.addTo(a.map);
return marker;
}
//添加大量的文本 使用canvas
addLayerUseCanvas (latlng, text) {
L.canvas().addLayer(L.marker(latlng).bindPopup(text));
}
//图像图层
ImageLayers(imageUrl, imageBounds, className = "") {
const a = this;
// var imageUrl = "http://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg",
// imageBounds = [[40.712216, -74.22655], [40.773941, -74.12544]];
var imageLayer = L.imageOverlay(imageUrl, imageBounds, {
opacity: 1, //图像透明度
interactive: true, //为true时
zIndex: 0, //显示层级
className: className, //类名
}).addTo(a.map);
return imageLayer;
}
//移除图层根据类名
removeLayersByAttr(className) {
var layers = this.getAllLayers(this.map);
for (var l in layers) {
if (layers[l].options.className == className) layers[l].remove();
}
}
//移除图层
removeLayers(layer) {
layer.remove();
}
//获取全部图层
getAllLayers(map) {
var allLayers = map._layers;
return allLayers;
}
//标记点绑定弹窗
markWithPopup(marker, popupContent) {
popupContent = "<p>Hello world!<br />This is a nice popup.</p>";
marker.bindPopup(popupContent).openPopup();
}
//弹窗
popupBox(latlng) {
const a = this;
latlng = [33.5, 113.5];
var popup = L.popup()
.setLatLng(latlng)
.setContent("<p>Hello world!<br />This is a nice popup.</p>")
.openOn(a.map);
return popup;
}
//关闭弹窗
closePopupBox(popup) {
popup.closePopup();
}
//交互事件
addMapEvent() {
const a = this;
a.map.on("click", function (e) {
var latlng = e.latlng, //经纬度
_taget = e.target, //target
pos = e.layerPoint || e.containerPoint; //屏幕位置
console.log(latlng, _taget, pos);
});
}
//移除交互事件
removeMapEvent() {
const a = this;
a.map.off("click", function (e) {
console.log(e);
});
}
}
export { LeafletMap };
二、vue引用
javascript
<template>
<div class="index">
<div class="map" id="mapContainer"></div>
</div>
</template>
<script>
import { LeafletMap } from "@/utils/leafletMap.js";
export default {
data() {
return {
areaCode:10,
LMap: null,
divMap: null, //地图map
pointMarker: null,
markClusterLayer: null, //聚合
allMarkers: [], //要聚合的点图层
};
},
mounted() {
this.initMap();
},
// 方法集合
methods: {
initMap() {
let dom = document.getElementById("mapContainer");
dom.innerHTML = "";
this.LMap = new LeafletMap();
let Areacode = this.areaCode,
{ center, zoom, minZoom, maxZoom } = configItem.mapConfig[Areacode];
this.divMap = this.LMap.init({
domId: "mapContainer",
center: [center[1], center[0]],
zoom: zoom,
minZoom,
maxZoom,
});
this.LMap.addGDLayers();
this.markClusterLayer = this.LMap.addClusterLayer();
this.mapClick();
this.mapZoomEnd();
this.areaBoundary();
},
//行政边界
areaBoundary() {
const env = process.env.NODE_ENV;
var str = env === "development" ? "/" : "../";
var jsonUrl = common.getStaticFile(
str + "static/areaJson/" + this.areaCode + ".json"
);
axios.get(jsonUrl).then((xcJson) => {
var myStyle = {
color: "#000",
fillColor: "transparent",
weight: 2,
fillOpacity: 1,
};
this.LMap.addBounds(xcJson.data, myStyle);
});
},
//行政名称
addAreaName() {
const env = process.env.NODE_ENV;
var str = env === "development" ? "/" : "../";
var jsonUrl = common.getStaticFile(
str + "static/areaPoint/" + this.areaCode + ".json"
);
axios
.get(jsonUrl)
.then((res) => {
res.data.forEach((item) => {
var marker = this.LMap.addTextLayer(
item.latlng,
item.label,
"areaName"
);
this.divMap.addLayer(marker);
this.areaNameLayers.push(marker);
});
})
.catch((e) => console.log(e));
},
mapClick() {
const env = process.env.NODE_ENV;
var str = env === "development" ? "/" : "../";
var jsonUrl = common.getStaticFile(
str + "static/areaPolygon/" + this.areaCode + ".json"
);
axios.get(jsonUrl).then((jsonData) => {
this.areaPolygon = jsonData.data;
this.divMap.on("click", (event) => {
this.removePoint();
let { lat, lng } = event.latlng;
var pt = turf.point([lng, lat]);
var poly = turf.polygon(this.areaPolygon);
var isTrue = turf.booleanPointInPolygon(pt, poly);
if (isTrue) {
//添加点图层
this.pointMarker = this.LMap.addIconLayers([lat, lng], {
iconUrl: common.getAssetsFile("pos.png"),
});
this.$refs.ForecastBox.DialogVisible = true;
this.$refs.ForecastBox.loadData(lng, lat);
}
});
});
},
mapZoomEnd() {
// 监听地图缩放后重新聚合
this.divMap.on("zoomend", (e) => {
// var zoom = this.divMap.getZoom();
if (this.allMarkers.length > 0 && this.markClusterLayer) {
this.markClusterLayer.clearLayers(); // 清除所有标记后重新添加以触发重新聚合
this.markClusterLayer.addLayers(this.allMarkers);
}
});
},
//等值面图|格点值
changeShowWay(ybTime) {
//清除图层
if (this.dztLayer) {
this.LMap.removeLayers(this.dztLayer);
this.dztLayer = null;
}
if (this.sztLayer) {
this.LMap.removeLayers(this.sztLayer);
this.sztLayer = null;
}
if (this.areaNameLayers.length > 0) {
this.areaNameLayers.forEach((layer) => {
this.LMap.removeLayers(layer); //移除图层
});
this.areaNameLayers = [];
}
this.legendData = [];
//移除聚合点
this.markClusterLayer.clearLayers();
},
//加载格点数值
loadGridData(resData, unit) {
let {
Data: gridData,
MaxLat,
MaxLon,
MinLat,
MinLon,
Width,
Height,
} = resData;
var dx = (MaxLon - MinLon) / Width,
dy = (MaxLat - MinLat) / Height;
var numArray = [];
const env = process.env.NODE_ENV;
var str = env === "development" ? "/" : "../";
var jsonUrl = common.getStaticFile(
str + "static/mapPoint/" + this.areaCode + ".json"
);
axios.get(jsonUrl).then((jsonData) => {
var mapData = jsonData.data,
layers = [];
for (var i = 0; i < gridData.length; i++) {
var row = gridData[i];
for (var j = 0; j < row.length; j++) {
var text = row[j],
x = j,
y = gridData.length - i - 1;
if (text < 99999 && mapData[y][x] == 1) {
var latlng = [MinLat + dy * i, MinLon + dx * j];
var layer = this.LMap.addTextLayer(
latlng,
text + unit,
"divText"
);
layers.push(layer);
// numArray.push({ label: text, x, y });
}
}
}
this.allMarkers = layers;
this.markClusterLayer.addLayers(layers);
if (numArray.length > 0) {
var canvas = document.createElement("canvas"),
ctx = canvas.getContext("2d"),
textW = 70,
textH = 50,
sumW = Width * textW,
sumH = Height * textH;
canvas.width = sumW;
canvas.height = sumH;
for (var o of numArray) {
ctx.fillStyle = "#000"; // 设置文本颜色为白色
ctx.font = "20px Arial"; // 设置字体大小和类型
ctx.textAlign = "center"; // 设置文本对齐方式为居中
ctx.textBaseline = "middle"; // 设置文本基线为中间
var value = o.label,
text = value < 99999 ? value + unit : "";
text &&
ctx.fillText(
text,
(o.x - 0.5) * textW + textW / 2,
(o.y + 1.2) * textH + textH / 2
); // 在矩形中心绘制文本"Hello, Canvas!"
}
var imageUrl = canvas.toDataURL("image/png");
var imageBounds = [
[MinLat, MinLon],
[MaxLat, MaxLon],
];
this.dztLayer = this.LMap.ImageLayers(imageUrl, imageBounds, "szt");
}
});
},
//移除图标点
removePoint() {
if (this.pointMarker) {
this.LMap.removeLayers(this.pointMarker);
this.pointMarker = null;
}
},
},
watch: {},
};
</script>
<style rel="stylesheet/less" lang="less" scoped>
.map{width:100%;height:100%;}
</style>
三、手动绘制L.Draw
安装与引用
npm i leaflet-draw --save
import "leaflet-draw";
import "leaflet-draw/dist/leaflet.draw.css";
使用
1、单个绘图工具控制
通过
L.Draw.Marker/Circle/Polyline
等类实例化后调用enable()
/disable()
方法例:
var drawObj = new L.Draw.Marker(map, options); drawObj.enable(); // 启用 drawObj.disable(); // 禁用
2、整个
var drawControl = new L.Control.Draw({ position: 'topright', draw: { polyline: true, polygon: true, rectangle: true, circle: true, marker: true } }).addTo(map);