目录
一、导入leaflet并初始化地图
1、安装leaflet模块
npm install leaflet
2、在style.less全局样式文件中引入leaflet.css
@import '../node_modules/leaflet/dist/leaflet.css';
3、创建map组件,定义一个地图容器,,id设置就是后面引用的地图容器名字,记得设置高度
<div id="map" style="height: 100%;width: 100%;margin: 0;padding: 0;"></div>
4、ts文件引入leaflet和初始化地图主要代码
import { Component } from '@angular/core';
import * as L from 'leaflet' //导入模块
@Component({
selector: 'app-map',
templateUrl: './map.component.html',
styleUrls: ['./map.component.less']
})
export class MapComponent {
map: any
layer: any
ngOnInit() {
this.initMap() //初始化地图
}
initMap() {
this.map = L.map('map', {//这里的‘map’,就是div容器的id
zoom: 13,//默认缩放级别
center: [31, 117]//中心点
})
this.layer = L.tileLayer('http://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',//瓦片链接
{
maxZoom: 18,//最大缩放级别
zIndex: 10//层级,越高,图层越上面
}).addTo(this.map)//add进地图里,才能显示出来
}
}
5、页面展示
二、地图基本操作
1、地图上添加标记Mark
L.marker([31, 117]).addTo(this.map);//在位置[31, 117]添加一个标记
2、地图上画圆
L.circle([31, 117], {
color: 'green',//边框颜色
fillColor: '#f03',//填充颜色
fillOpacity: 0.5,//透明度
radius: 200//圆的半径
}).addTo(this.map)
3、地图上画多边形
let latlngs = [
[31, 117] as LatLngExpression, //类型断言 不然下面引用会报错
[31.01, 117.05] as LatLngExpression,
[31.02, 117.05] as LatLngExpression,
];
let polygon=L.polygon(latlngs, {
color: 'green',
fillColor: 'red',//填充颜色
}).addTo(this.map)
// 将地图放大到多边形的位置
this.map.fitBounds(polygon.getBounds());
4、地图上绘制弹出框(Popup)
let marker = L.marker([31, 117]).addTo(this.map);//在位置[31, 117]添加一个标记
marker.bindPopup('marke').openPopup() //.openPopup()表示默认打开,地图上只允许同时打开1个,或者使用 Map.addLayer 打开任意多个。
.....
polygon.bindPopup('<p style="color:red">Hello world!<br />这是一个绘制的多边形</p>')
都用这个方法加弹框,就可以同时显示多个
marker.bindPopup('marke').openPopup()
L.popup().setLatLng([31.01, 117])
.setContent('<p style="color:red">Hello world!<br />这是一个绘制的多边形</p>')
.addTo(this.map)
L.popup().setLatLng([31.015, 117])
.setContent('<p style="color:red">Hello world!<br />这是一个绘制的多边形</p>')
.addTo(this.map)
5、简单click事件响应,点击显示经纬度
this.map.on('click', (e: any) => { //简单的地图点击事件响应,绘制弹出框显示经纬度
L.popup().setLatLng([e.latlng.lat, e.latlng.lng])
.setContent(`纬度:${e.latlng.lat}<br/>经度:${e.latlng.lng}`)
.addTo(this.map)
})
对地图实例做监听,在Leaflet中每种实现对象都可以添加事件。
//对地图实例做监听,在Leaflet中每种实现对象都可以添加事件
marker.on('click',(e:any)=>{
L.popup().setLatLng(e.latlng).setContent('我被点击了').addTo(this.map)
})
6、切换地图底图
添加一个basemaps地图底图图层对象,初始化地图并设置底图图层,添加图层控制器
//定义了一个 basemaps 对象,包含了一些不同的底图图层选项
var basemaps = {
世界影像: L.tileLayer('http://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
attribution: '添加地图图层的归属声明,地图数据的来源和相关版权信息。通常会显示在地图的角落'
}),
arc街道: L.tileLayer('http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}'),
'行政区': L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/Reference/World_Reference_Overlay/MapServer/tile/{z}/{y}/{x}'),
'地形': L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Terrain_Base/MapServer/tile/{z}/{y}/{x}'),
};
this.map = L.map('map', {//这里的‘map’,就是div容器的id
layers: [basemaps.世界影像], // 设置默认显示的底图
zoom: 13,//默认缩放级别
center: [31, 117]//中心点
})
L.control.scale().addTo(this.map);//添加比例尺
L.control.layers(basemaps).addTo(this.map); //使用 L.control.layers(basemaps).addTo(map) 添加了一个图层控制器,允许用户在不同的图层之间进行切换
7、实现输入经纬度跳转
<div>
<input type="number" #jingdu>
<input type="number" #weidu>
<button (click)="location(jingdu.value,weidu.value)">定位</button>
</div>
// 声明一个成员变量保存当前标记
private marker?: L.Marker;
location(a: any, b: any) {
if (this.marker) {
this.map.removeLayer(this.marker)//清除上一个标记点
}
this.marker = L.marker([a, b]).addTo(this.map)//添加标记点
this.map.flyTo([a, b])//fly到坐标点的位置
this.map.planTo([a, b])//平移到坐标点的位置,动画效果不顺滑
}
8、angular引入leaflet插件
①下载插件
②打开插件的index.html,查看引用的样式和js文件,
③把这几个文件放到angular项目的index.html文件中。
④angular.json文件中全局引用一下leaflet-side-by-side.js文件
⑤配置插件被ts识别,终端输入。操作完成后,会在node_modules文件夹下生成@types下leaflet-side-by-side文件夹。可查看文件夹下的index.d.ts文件。导入完成可正常使用插件了。
npm install @types/leaflet-side-by-side --save
除此外,某些插件可以直接npm安装
npm install leaflet-side-by-side
安装插件时的一些报错解决方法:
①需要修改WEBPACK 配置和自定义 LOADER 处理实例
安装webpack插件,版本号根据angular cli来
npm i -D @angular-builders/custom-webpack@16.0.0
添加webpack.config.js文件,文件内容为:
module.exports = {
// ...其他配置...
module: {
rules: [
// 处理 .css 文件
{
test: /\.css$/,
use: [
// 将 CSS 插入到 DOM 中
'style-loader',
// 将 CSS 转换为 JavaScript 模块
'css-loader',
],
},
],
},
};
修改angular.json文件
"architect": {
"build": {
"builder": "@angular-builders/custom-webpack:browser",
//.....省略....
"customWebpackConfig": {
"path": "./webpack.config.js"
},
//.....省略....
},
"serve": {
"builder": "@angular-builders/custom-webpack:dev-server",
//.....省略....
},
②找不到模块
npm 安装
npm install style-loader
9、实现地图卷帘效果,叠加显示
分别定义左右两个地图图层
let leftLayers = L.tileLayer(`https://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}`);
let rightLayers = L.tileLayer(`http://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}`);
使用sideBySide()方法,三个属性
L.control.sideBySide(rightLayers, rightLayers).addTo(this.map)
// 参数分为别左、右图层(数组)、选项配置
L.control.sideBySide(leftLayer[s], rightLayer[s],options)
let sideBySide = L.control.sideBySide(leftLayers, [rightLayersText, rightLayers], { padding: 0, thumbSize: 42 }).addTo(map);
// 修改左侧图源
sideBySide.setLeftLayers(purplishBlueLayer)
// 修改右侧图源
// sideBySide.setRightLayers(purplishBlueLayer)
效果图,可左右滑动,拖动地图
10、画各种线
安装 PolylineDecorator 插件:
npm install leaflet-polylinedecorator
配置插件被ts识别
npm install @types/leaflet-polylinedecorator --save
在ts里面导入后就可以正常使用了
import 'leaflet-polylinedecorator';
①带一个箭头的线
let arrow = L.polyline([//画一段普通线
[30, 105],
[30.5, 104],
[30.6, 105.2],
[30.7, 104.8],
], {}).addTo(this.map);
L.polylineDecorator(arrow, {//生成带箭头线
patterns: [{
offset: '100%',//符号的起点为折线的终点。
repeat: 0,//只应用一次该符号模板,不重复。
//表示装饰的图案效果为一个箭头
symbol: L.Symbol.arrowHead({
pixelSize: 15,//箭头的大小,15 像素。
polygon: false,//箭头的形状为点到线的箭头而非多边形。
pathOptions: {
stroke: true//箭头应用与折线相同的线条配置,这里表示使用折线的线条样式(颜色、宽度等)。
}
})
}]
}).addTo(this.map);
②虚线/面
let polygon = L.polygon([ //绘制一个面
[
[54, -6],
[55, -7],
[56, -2],
[55, 1],
[53, 0]
],
[
[54, -3],
[54, -2],
[55, -1],
[55, -5]
]
], {
color: "#ff7800",
weight: 3
}).addTo(this.map);
L.polylineDecorator(polygon as any, {
// patterns:定义装饰的图案效果
patterns: [{
offset: 0,//符号的起点为多边形的起点
repeat: 10,//每隔一定的距离(这里为符号的长度)就重复一次该符号,直到覆盖整个多边形。
symbol: L.Symbol.dash({//装饰的图案效果为无间隔虚线,每条线段的长度为 pixelSize 像素。pixelSize 被设置为 0,表示线段长度为默认值(5 像素)。
pixelSize: 0
})
}]
}).addTo(this.map);
③点线点线效果
let aa = L.polyline([
[49.543519, -12.469833],
[49.808981, -12.895285],
[50.056511, -13.555761],
[50.217431, -14.758789],
[50.476537, -15.226512],
[50.377111, -15.706069],
[50.200275, -16.000263],
])
L.polylineDecorator(aa, {
patterns: [{
offset: 12,//符号的起点距离折线的起点的长度为 12 个像素。
repeat: 25,
//装饰的图案效果为一条红色的虚线,每条线段的长度为 10 个像素
symbol: L.Symbol.dash({
pixelSize: 10,
pathOptions: {
color: '#f00',
weight: 5
}
})
},
{//示装饰的图案效果为一条实线
offset: 0,
repeat: 25,
symbol: L.Symbol.dash({
pixelSize: 0
})
}
]
}
).addTo(this.map);
④带标记点的线
let markerLine = L.polyline([
[58.44773, -28.65234],
[52.9354, -23.33496],
[53.01478, -14.32617],
[58.1707, -10.37109],
[59.68993, -0.65918]
], {}).addTo(this.map);
L.polylineDecorator(markerLine, {
patterns: [{
offset: '5%',
repeat: '10%',
symbol: L.Symbol.marker()//标记符号是一个圆形,可以通过传递配置选项对象修改其外观。
}]
}).addTo(this.map);
⑤带自定义图案的线
let aaa = L.polyline([
[42.9, -15],
[44.18, -11.4],
[45.77, -8.0],
[47.61, -6.4],
[49.41, -6.1],
[51.01, -7.2]
])
L.polylineDecorator(aaa, {
patterns: [{
offset: 0,
repeat: 10,
symbol: L.Symbol.dash({ //黑色透明度0.2宽度2px的虚线
pixelSize: 5,
pathOptions: {
color: '#000',
weight: 2,
opacity: 0.2
}
})
},
{
offset: '16%',
repeat: '33%',
symbol: L.Symbol.marker({
rotate: true,
markerOptions: {
icon: L.icon({
iconUrl: './assets/images/icon_plane.png',//自定义的飞机图案
iconAnchor: [16, 16]
})
}
})
}
]
}
).addTo(this.map);
⑥带多箭头的线
let multiCoords1 = [
[
[47.5468, -0.7910],
[48.8068, -0.1318],
[49.1242, 1.6699],
[49.4966, 3.2958],
[51.4266, 2.8564],
[51.7542, 2.1093]
],
[
[48.0193, -2.8125],
[46.3165, -2.8564],
[44.9336, -1.0107],
[44.5278, 1.5820],
[44.8714, 3.7353],
[45.8287, 5.1855],
[48.1953, 5.1416]
],
[
[45.9205, 0.4394],
[46.7699, 0.9228],
[47.6061, 2.5488],
[47.7540, 3.3837]
]
] as LatLngExpression[][];
let plArray = [];
for (let i = 0; i < multiCoords1.length; i++) {
//在每次迭代中,创建一个新的 Polyline 对象,
plArray.push(L.polyline(multiCoords1[i]).addTo(this.map));
}
L.polylineDecorator(plArray, {
patterns: [{
offset: 25,
repeat: 50,
//表示装饰的图案效果为一个箭头符号。箭头的大小为 15 个像素。该符号模板还设置了箭头的颜色透明度为 1,线宽为 0。
symbol: L.Symbol.arrowHead({
pixelSize: 15,
pathOptions: {
fillOpacity: 1,
weight: 0
}
})
}]
}).addTo(this.map);
11、定位用户位置(精度较低)
①leaflet自带的方法
this.map.locate({
setView: true, // 是否将地图视角移动到当前位置
maxZoom: 18, // 最大缩放级别
watch: true, // 是否持续监听位置变化
enableHighAccuracy: true ,// 是否启用高精度定位(可能会耗费更多的时间和电量)
timeout: 100000 // 设置 timeout 选项为 10 秒
});
this.map.on('locationfound', (e: any) => {
if (this.marker) {
this.marker.setLatLng(e.latlng); // 更新标记的位置
} else {
this.marker = L.marker(e.latlng).addTo(this.map).bindPopup("<b>你在这儿!</b>").openPopup(); // 创建标记并添加到地图
}
});
②使用leaflet.locate插件
安装插件、使ts识别,导入
npm install --save leaflet.locatecontrol
npm install @types/leaflet.locatecontrol --save
import 'leaflet.locatecontrol' // Import plugin
import 'leaflet.locatecontrol/dist/L.Control.Locate.min.css'
实现代码
L.control.locate({
position: "topright",//定位按钮放在右上角
initialZoomLevel: 15,//开始的缩放级别
strings: {
title: "Show me where I am, yo!"
},
locateOptions: {
maxZoom: 16,// 设置最大缩放级别
},
}).addTo(this.map);
点击定位按钮跳转
使用画图工具栏
npm install leaflet-draw
npm install @types/leaflet-draw