参考仓库:
leaflet基本用法
1.引入leafletjs资源:
- 手动 下载地址:https://leafletjs.com/download.html 引入css和js
- npm npm install leaflet --save 在组件或者main.js中引入
2.创建容器存放地图
<div id="map"></div>
3.初始化地图
坐标,纬度在前,经度在后,初始化地图必有两个参数,一个坐标,一个初始缩放倍数
<script setup>
import L from 'leaflet'
import 'leaflet/dist/leaflet.css'
import { onMounted} from 'vue'
const initMap = () => {
let map = L.map('map', {
center: [29.44916482692468, 106.47399902343751],//中心坐标
zoom: null,//初始缩放,因为在下文写了展示全地图,所以这里不设置,也可以设置
minZoom: 3,
maxZoom: 18,
zoomControl: true, //缩放组件
// attributionControl: false, //去掉右下角logol
})
// let map=L.map("map").setview([29.44916482692468, 106.47399902343751],9);
}
onMounted(() => {
initMap()
})
</script>
4.给容器设置宽高,显示地图
<style>
#map {
height: 800px;
width: 1000px;
margin: auto;
border: 10px solid pink;
}
</style>
leaflet布局,图层
L.tileLayer加载底图,第一个参数为底图资源,第二个参数中attribution为版权
L.tileLayer(
"https://webrd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}",
{
attribution:
'© <p>OpenStreetMap</p> contributors',
}
).addTo(map);
leaflet标记
使用L.marker()第一个参数为经纬度,第二个参数为自定义标记图标。
addTo()添加到图层;bindPopup()显示弹框内容,openPopup()自动打开弹框。
弹框也可使用bindTooltip()
let markerIcon = L.icon({
iconUrl: "https://unpkg.com/leaflet@1.9.3/dist/images/marker-icon.png",
iconSize: [20, 30],
});
let marker = L.marker([29.44916482692468, 106.47399902343751], { icon: markerIcon })
.addTo(map)
.bindPopup("标记")
.openPopup();
//--------------------------------
//marker.bindTooltip('我是标记', { //添加提示文字
// permanent: true, //是永久打开还是悬停打开
//direction: 'top' //方向
//}).openTooltip(); //在图层打开
leaflet线段,形状
线段:使用 L.polyline()第一个参数为线段两端的位置坐标,第二个参数为线段的样式。
同样也可使用弹框来做数据展示。
let line = L.polyline([[29.44, 106.473], [27.595, 106.9]],
{
opacity: 1,
color: 'red'
}).addTo(map)
圆形:使用 L.circle(),对于圆形只需要一个坐标和圆的半径;第一个参数为圆点,第二个参数为圆的样式。同样也可使用弹框来做数据展示。
L.circle([29.44, 106.473], {
color: "black", //轨迹颜色
fillColor: "pink", //默认和轨迹色一样
fillOpacity: 0.3, //圆的填充色
radius: 500 * 100, //半径,单位为米
}).addTo(map);
矩形:使用 L.rectangle(),对于矩形有对角线只需要确定两个坐标;第一个参数为坐标,第二个参数为矩形的样式
let rectangle = L.rectangle(
[29.44, 106.473],
{ color: "pink" }
).addTo(map);
多边形:使用L.polygon(),该坐标为数组,长度大于2,。
let polygon = L.polygon(坐标数组, { color: "red" }).addTo(map);
leaflet弹框
使用L.popup()如下,弹框中的内容可以是变量也可以展示dom元素。
L.popup({
closeButton: true, //是否有关闭按钮
closeOnClick: true, // 点击空白是否关闭
className: "pop-style", //弹框样式类名
})
.setLatLng(坐标) // 弹框坐标
.setContent(content) //弹框内容 可动态内容
// .setContent("你好xxx")
.openOn(map);
leaflet事件
点击获取到的e.latlng是所点击位置的经纬度坐标。可使用map.setView()重置中心位置和缩放倍数。
在以上的部分中,需要用到坐标的都在事件中进行获取,可以用数组收集起来展示多边形。
let arrLatlng = [];
map.on("click", function (e) {
let latlng = e.latlng;
map.setView(latlng, 7);
//动态线段
arrLatlng.push(latlng);
if (arrLatlng.length > 1) {
// 线段 连续线段--------------------------------------
let line = L.polyline(
[arrLatlng[arrLatlng.length - 2], arrLatlng[arrLatlng.length - 1]],
{
opacity: 1,
color: "green",
}
).addTo(map);
}
})
leaflet底图切换
定义一些地图底层瓦片数据,在第一条数据调用addTo(map),表示默认展示地图;在L.tileLayer()中将两个参数置空,也可以设置默认值。
对于osm地图无法显示:leaflet+Openstreetmap地图无法显示_leaflet openstreetmap 地址-CSDN博客
瓦片数据地址:https://zhuanlan.zhihu.com/p/641436984
通过L.control.layers()创建一个Layer Control,参数:
1.第一个参数是创建的包含所有底图的对象baseLayer;
2.第二个参数是覆盖Layer对象的图层;
3.底图控制的位置
// 地图底层数据
const baseLayer = {
'高德地图': L.tileLayer(
"https://webrd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}",
{ attribution: "高德" }
).addTo(map),
'ArcGIS卫星影像': L.tileLayer( "https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}.png",
{ attribution: "ArcGIS卫星影像" }
),
'白色底图': L.tileLayer(
"http://10.87.211.254:8099/title/{z}/{x}/{y}.png",
{ attribution: "白色底图" }
),
'天地图影像图': L.tileLayer(
"http://t3.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=d0cf74b31931aab68af181d23fa23d8d",
),
'天地图街道图': L.tileLayer(
"http://t4.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=d0cf74b31931aab68af181d23fa23d8d",
),
}
// 配置布局
L.tileLayer("", { attribution: "版权归xxx" }).addTo(map);
// 地图底层控制
L.control.layers(
baseLayer, {}, {
position: 'topright'
}
).addTo(map)
leaflet.pm 图层
在Leaflet中,有两种Layer:(1)base layers——底图(在我们的GIS系统中一次只能显示一张底图);(2)overlays——覆盖Layer(放在底图上的Layer)。
使用L.layerGroup()来声明图层组,
let markerIcon = L.icon({
iconUrl: require("../leaflet/person1.png"),
iconSize: [50, 50],
});
//声明图层组,存储城市标记marker
let cities = L.layerGroup();
// 声明两个城市的坐标加入图层组
L.marker([29.44916482692468, 106.47399902343751], { icon: markerIcon }).bindPopup('这里属于重庆').addTo(cities);
L.marker([35.51, 117.92], { icon: markerIcon }).bindPopup('这里属于青岛').addTo(cities);
// 新建图层控件的数据源 - 城市
let overlays = {
'城市': cities
};
L.control.layers(
baseLayer, overlays, {
position: 'topright'
}
).addTo(map)
leaflet.pm 几何图形的编辑
需要安装leaflet.pm插件 / 也可使用安装Leaflet-Geoman/也可以使用leaflet-drawLeaflet-draw使用方法(个人觉得该编辑插件最好用) 使用之前卸载leaflet.pm
npm install leaflet.pm
页面引入
import 'leaflet.pm';
import 'leaflet.pm/dist/leaflet.pm.css';
在组件中运用
map.pm.setLang()函数使工具条提示显示中文; map.pm.addControls()增加图形绘制控件
// 添加绘制工具
map.pm.setLang('zh')
map.pm.addControls({
position: "topleft",
drawPolygon: true, //绘制多边形
drawMarker: false, //绘制标记点
drawCircleMarker: false, //绘制圆形标记
drawPolyline: true, //绘制线条
drawRectangle: false, //绘制矩形
drawCircle: false, //绘制圆圈
editMode: true, //编辑多边形
dragMode: true, //拖动多边形
cutPolygon: true, //添加⼀个按钮以删除多边形⾥⾯的部分内容
removalMode: true, //清除多边形
})
// 全局绘制样式
map.pm.setPathOptions({
color: "orange",
fillColor: "green",
fillOpacity: 0.4,
})
// 或者单独设置绘制样式
let options = {
// 连接线标记之间的线 实线
templineStyle: {
color: "red",
},
// 提⽰线从最后⼀个标记到⿏标光标的线虚线
hintlineStyle: {
color: "red",
dashArray: [5, 5],
},
// 绘制完成的样式
pathOptions: {
color: "orange",
fillColor: "green",
},
}
// 激活绘制多边形功能、绘制多边形时的样式
map.pm.enableDraw("Polygon", options)
// 启用绘制--多边形功能
map.pm.enableDraw("Polygon", {
snappable: true, //启⽤捕捉到其他绘制图形的顶点
snapDistance: 20, //顶点捕捉距离
})
// 关闭绘制--注意也可以关闭其他模式的绘制功能
map.pm.disableDraw("Polygon")
// 绘制事件监听
map.on("pm:drawstart", (e) => {
console.log(e, "绘制开始第一个点");
})
map.on("pm:drawend", (e) => {
console.log(e, "禁⽌绘制、绘制结束");
})
map.on("pm:create", (e) => {
console.log(e, "绘制完成时调⽤");
if (e.shape == "Circle") {
console.log(e.layer._latlng, e.layer._radius, "绘制坐标");
} else {
console.log(e.layer._latlngs[0], "绘制坐标");
}
})
map.on("pm:globalremovalmodetoggled", (e) => {
console.log(e, "清除图层时调用");
})
leafletGeoJson格式数据应用
geoJson是一种基于Json的地理空间数据交换格式。它定义了几种类型的json对象,以及将他们结合起来表示有关地理特征、属性和空间范围的数据的方式。
推荐一篇文章关于GeoJson对象解释以及他的几何类型:GeoJSON三分钟入门教程 - 知乎 (zhihu.com)
应用geojson数据:可以定义一个geojson格式数据,( 中国各地geojson格式数据来源:DataV.GeoAtlas地理小工具系列 (aliyun.com))如下:
var geojsonFeature={
"type": "Feature",
"properties": {
"name": "Coors Field",
"amenity": "Baseball Stadium",
"popupContent": "This is where the Rockies play!"
},
"geometry": {
"type": "Point",
"coordinates": [-104.99404, 39.75621]
}
};
通过L.geoJson(数据,样式)来解析这种数据结构,以下通过axios获取:
const getData = function () {
axios.get('https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json')
.then(function (res) {
let list = res.data
const lakeLayer = L.geoJson(list, {
style: {
weight: 2, //外边框宽度
opacity: 0.2,
color: 'black',//外边框颜色
fillOpacity: 0.2,//填充透明度
fillColor: '#6ba7de'//填充的颜色
},
}).addTo(map);
})
.catch(function (error) {
console.log(error);
})
}
除此之外,还可以先创建一个geoJosn的空图层,然后后面再添加格式进去:
let myLayer=L.geoJSON().addTo(map)
myLayer.addData(list)
onEachFeature函数,可以遍历集中的所有要素feature,并为要素赋予一些属性或进行一些操作,如下:
可以对获得的范围进行点击,鼠标移动事件,feature是遍历出的单独小版块,和触发事件e.target.feature一样,layer则是触发事件e.target,通过bindTooltip()鼠标经过哪些部分就可以展示相应的内容。
// 创建geoJson图层
const lakeLayer = L.geoJson(list, {
style: lakeLayerstyleNew,
onEachFeature: ((feature, layer) => {
layer.on({
//鼠标移入方法
mouseover: (() => {
parentCode = feature.properties.parent.adcode
// 移入的效果
if (parentCode == adcode.value) {
layer.setStyle({
weight: 2,
color: '#2f8ffc',
fillColor: '#ffffff',
fillOpacity: 0.4,
});
}
}),
//鼠标移出方法
mouseout: (() => {
if (parentCode == adcode.value) {
layer.setStyle(lakeLayerstyleNew);
}
}),
//点击方法,变色
click: (() => {
layer.setStyle({
weight: 4,
color: 'red',
});
// 获取code
adcode.value = feature.properties.adcode;
level.value = feature.properties.level
}),
});
})
}).bindTooltip(function (layer) { // 只要使用这个bindTooltip方法,
// 弹框内容
let content = 'adcode:' + `${layer.feature.properties.adcode}` + '<br/>' + 'name:' + `${layer.feature.properties.name}` + '<br/>' + 'level:' + `${layer.feature.properties.level}`
return content;
}).addTo(map);
//定位到该图层 显示geoJson图层整个视图,若不加,则会展示初始位置视图范围
// fitBounds用于调整地图的视图以适应指定的边界。
map.fitBounds(lakeLayer.getBounds());
问题
- 以 http://localhost:8080/打开,编辑图层的功能,编辑多边形不可用,卡死,获取的geojson数据视图展示出;以 http://192.xxx.xx.xxx/打开,编辑图层可用,但,获取的geojson数据展示不出。
解决
localhost运行能展示geojson数据,通过电脑IP运行展示不出,公共资源访问403,原因:在我们请求的时候会带我们的浏览器信息到阿里云,阿里云做了访问限制
在Vue 3中,你可以通过在项目的
public/index.html
文件中直接添加<meta>
标签来配置referrer-policy
。这样做可以确保在你的Vue应用中所有的HTTP请求都不会发送Referer
头部。