Leaflet 常用插件

参考: leaflet实用插件整理

1、Leaflet.AntPath 将通量动画(如蚂蚁行走)放入折线中

leaflet-ant-path:https://www.npmjs.com/package/leaflet-ant-path

在交通项目、管网应用的项目中,常常需要标注出道路的走向、河流的流向或者管线的流向等等,Leaflet Ant Path 能够很好的解决这类问题。
在这里插入图片描述
官网示例: https://rubenspgcavalcante.github.io/leaflet-ant-path/
在这里插入图片描述

安装:

npm i leaflet-ant-path

引用:

 import { AntPath, antPath } from 'leaflet-ant-path';

使用:

<template>
  <div id="map"></div>
</template>

<script lang="ts" setup>
import L from "leaflet";
import { onMounted, onBeforeUnmount } from "vue";
// @ts-ignore
import { antPath } from "leaflet-ant-path";
import route from "./route";
import { ATTRIBUTIONS } from "../../../constants";

let map: L.Map | null = null;
const initMap = () => {
  //地图容器
  map = L.map("map", {
    //参考坐标系
    crs: L.CRS.EPSG3857,
    //显示中心
    center: [30.5217, 114.3948],
    //当前显示等级
    zoom: 18,
  });

  //加载天地图矢量图层
  L.tileLayer(
    "http://t0.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=55b4d4eaef95384c946e9bd1b99c5610",
    { noWrap: true, attribution: ATTRIBUTIONS }
  ).addTo(map);
  //加载天地图矢量注记图层
  L.tileLayer(
    "http://t0.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=55b4d4eaef95384c946e9bd1b99c5610",
    { noWrap: true, attribution: ATTRIBUTIONS }
  ).addTo(map);
  const path = antPath(route, {
    delay: 400,
    dashArray: [10, 20],
    weight: 5,
    color: "#0000FF",
    pulseColor: "#FFFFFF",
    paused: false,
    reverse: false,
    hardwareAccelerated: true,
  });

  map.addLayer(path);
  map.fitBounds(path.getBounds());
};

onMounted(() => {
  initMap();
});

// 销毁地图
onBeforeUnmount(() => {
  if (map) {
    map.remove();
    map = null;
  }
});
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
#map {
  height: 650px;
  color: #3a3a3a;
}
</style>

在这里插入图片描述

2、Leaflet.Path.DashFlow 对直线和圆圈的dashArray进行动画处理,创造一个基本的流动效果

参考:支持Canvas的Leaflet.Path.DashFlow动态流向线

插件可实现轨迹动态展示、管道流向动态展示、河流流向动态展示等,达到增强可视化展示的效果。

在这里插入图片描述
在这里插入图片描述
使用:

在项目中直接引入 L.Path.DashFlow.js 文件。

L.Path.DashFlow.js

// @class PolyLine

L.Path.mergeOptions({
	// @option dashSpeed: Number
	// The speed of the dash array, in pixels per second
	dashSpeed: 0
});


var _originalBeforeAdd = L.Path.prototype.beforeAdd;

L.Path.include({

	beforeAdd: function (map) {
		_originalBeforeAdd.bind(this)(map);

		if (this.options.dashSpeed) {
			this._lastDashFrame = performance.now();
			this._dashFrame = L.Util.requestAnimFrame(this._onDashFrame.bind(this));
		}
	},

	_onDashFrame: function () {
		if (!this._renderer) {
			return;
		}

		var now = performance.now();
		var dashOffsetDelta = (now - this._lastDashFrame) * this.options.dashSpeed / 1000;

		this.options.dashOffset = Number(this.options.dashOffset || 0) + dashOffsetDelta;
		this._renderer._updateStyle(this);

		this._lastDashFrame = performance.now();

		this._dashFrame = L.Util.requestAnimFrame(this._onDashFrame.bind(this));
	},

	_offDashFrame: function () {
		L.Util.cancelAnimFrame(this._dashFrame);
	},

	onRemove: function () {
		this._renderer._removePath(this);
		this._offDashFrame();
	}
});


// 针对Canvas添加dashOffset参数,解决Canvas下无法实现动态线问题
L.Canvas.include({
	_updateDashArray: function (layer) {
		if (typeof layer.options.dashArray === 'string') {
			var parts = layer.options.dashArray.split(/[, ]+/),
				dashArray = [],
				dashValue,
				i;
			for (i = 0; i < parts.length; i++) {
				dashValue = Number(parts[i]);
				// Ignore dash array containing invalid lengths
				if (isNaN(dashValue)) {
					return;
				}
				dashArray.push(dashValue);
			}
			layer.options._dashArray = dashArray;
		} else {
			layer.options._dashArray = layer.options.dashArray;
		}

		if (layer.options.dashOffset) {
			layer.options._dashOffset = layer.options.dashOffset;
		}
	},
	_fillStroke: function (ctx, layer) {
		var options = layer.options;

		if (options.fill) {
			ctx.globalAlpha = options.fillOpacity;
			ctx.fillStyle = options.fillColor || options.color;
			ctx.fill(options.fillRule || 'evenodd');
		}

		if (options.stroke && options.weight !== 0) {
			if (ctx.setLineDash) {
				ctx.setLineDash(layer.options && layer.options._dashArray || []);
			}
			if (layer.options._dashOffset) {
				ctx.lineDashOffset = layer.options._dashOffset;
			}
			ctx.globalAlpha = options.opacity;
			ctx.lineWidth = options.weight;
			ctx.strokeStyle = options.color;
			ctx.lineCap = options.lineCap;
			ctx.lineJoin = options.lineJoin;
			ctx.stroke();
		}
	},
})

示例:

<!DOCTYPE html>
<html>
<head>
	<title>Leaflet debug page</title>

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.4.0/dist/leaflet.css"
  integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA=="
  crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.4.0/dist/leaflet.js"
  integrity="sha512-QVftwZFqvtRNi0ZyCtsznlKSWOStnDORoefr1enyq5mVL4tmKB3S/EnC3rRJcxCPavG10IcrVGSmPh6Qw5lwrg=="
  crossorigin=""></script>


<script src="L.Path.DashFlow.js"></script>

</head>
<body>
	<div id="map" style="width: 800px; height: 600px; border: 1px solid #ccc"></div>

	<script src="route.js"></script>
	<script>
		for (var i = 0, latlngs = [], len = route.length; i < len; i++) {
			latlngs.push(new L.LatLng(route[i][0], route[i][1]));
		}

		var path = L.polyline(latlngs, {
			dashArray: "15,15",
			dashSpeed: -30
		});

		var map = L.map('map');

		var positron = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {
			attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://cartodb.com/attributions">CartoDB</a>'
		}).addTo(map);


		map.fitBounds(L.latLngBounds(latlngs));

		map.addLayer(L.marker(latlngs[0]));
		map.addLayer(L.marker(latlngs[len - 1]));

		map.addLayer(path);

		L.circleMarker([10, 70], {
			dashArray: "15,15",
			dashSpeed: -30,
			radius: 147.5
		}).addTo(map);
		
	</script>
</body>
</html>

在这里插入图片描述

3、leaflet-icon-pulse :使用 CSS3 渲染脉冲图标。 它可用于位置标记

官方案例: http://mapshakers.com/projects/leaflet-pulse-icon/

在这里插入图片描述
下载和使用:

npm install @ansur/leaflet-pulse-icon

引入位于 \dist 目录中的 CSS 和 JavaScript 文件。

<script src="../L.Icon.Pulse.js" />
<link rel="stylesheet" href="../L.Icon.Pulse.css" />
var pulsingIcon = L.icon.pulse({iconSize:[20,20],color:'red'});
var marker = L.marker([50,15],{icon: pulsingIcon}).addTo(map);

在这里插入图片描述

4、Leaflet.Radar : 雷达扇区扫描动画

Leaflet.Radar: https://github.com/rwev/leaflet-radar

测试案例: http://examples.panzhiyue.website/leaflet.radar/examples/index.html

在这里插入图片描述

5、Leaflet.MovingMarker:允许以自定义的持续时间沿多段线移动标记

示例1: http://ewoken.github.io/Leaflet.MovingMarker/

示例2: https://zjffun.github.io/Leaflet.MovingMarker/examples/index.html

在这里插入图片描述

Leaflet中使用MovingMarker插件实现标记移动(轨迹回放效果)

Leaflet 带箭头轨迹以及沿轨迹带方向的动态marker

示例: http://gisarmory.xyz/blog/leaflet-RouteAnimate/demo.html

在这里插入图片描述

6、Esri Leaflet:一组用于将 ArcGIS 服务与 Leaflet 一起使用的工具。支持地图服务、要素图层、ArcGIS Online 切片等。

5分钟学会Leaflet加载天地图和arcgis服务

leaflet 加载arcgis发布的切片–L.esri.tiledMapLayer(影像),L.esri.dynamicMapLayer(矢量)

Esri Leaflet 官网示例

安装:

npm i esri-leaflet

在这里插入图片描述
在这里插入图片描述

7、Leaflet.ChineseTmsProviders:常用地图切换加载(TianDiTu、GaoDe、Google、OSM、Baidu)

安装:

npm i leaflet.chinatmsproviders

引用:

import "leaflet/dist/leaflet.css";
import L from "leaflet";
import "leaflet.chinatmsproviders";

使用:

      // 影像
      let imgm = L.tileLayer.chinaProvider('TianDiTu.Satellite.Map', {
        key: '6a9f4b408cb773ba60fb639f3b713d61',
        maxZoom: 18,
        minZoom: 3,
      })
      let imga = L.tileLayer.chinaProvider('TianDiTu.Satellite.Annotion', {
        key: '6a9f4b408cb773ba60fb639f3b713d61',
        maxZoom: 18,
        minZoom: 3,
      })

      this.imageLayer = L.layerGroup([imgm, imga])
      this.maps.addLayer(this.imageLayer)

在这里插入图片描述
注意: 使用 leaflet.chinatmsproviders 加载的地图均使用 EPSG:3857坐标参考系统(CRS)。

8、Leaflet.PM:用于在 Leaflet 1.0 中创建和编辑几何图形层的 Leaflet 插件

leaflet.pm

  • 具有绘制、编辑、拖拽、剪切和捕捉功能。
  • 在名称 "leaflet.pm "中,"pm"代表多边形管理。当时,该插件只支持多边形。现在,您可以编辑标记、多段线、多边形、圆、矩形、图层组、GeoJSON 以及更多即将推出的功能。

在这里插入图片描述

9、Leaflet-Geoman:用于创建和编辑几何图形层的 Leaflet 插件

说明: Leaflet 1.0 及更高版本的几何管理。 绘制、编辑、拖动、剪切、旋转、拆分、缩放、测量、捕捉和固定图层,如标记、CircleMarkers、折线、多边形、圆形、矩形、ImageOverlays、LayerGroups、GeoJSON、MultiLineStrings 和 MultiPolygons。 支持 polygons、canvas 模式等。

Leaflet-Geoman 官网: https://www.geoman.io/

Leaflet-Geoman 文档地址: https://www.geoman.io/docs

Leaflet-Geoman Demo在线地址: https://geoman.io/demo

使用教程: Leaflet-Geoman 帮助文档

Leaflet-Geoman学习笔记

在这里插入图片描述
leaflet-geoman 是一个商业化的插件,文档很详细,同时提供免费版本。

免费版本的功能同样强大,支持图形的绘制、编辑、拖动、剪切、分割、固定、跟踪、测量、缩放、旋转等操作。

免费版使用教程如下:

安装和使用:

npm 下载:

npm i @geoman-io/leaflet-geoman-free

CDN 在线引用:

CSS:

<link
  rel="stylesheet"
  href="https://unpkg.com/@geoman-io/leaflet-geoman-free@latest/dist/leaflet-geoman.css"
/>

JS:

<script src="https://unpkg.com/@geoman-io/leaflet-geoman-free@latest/dist/leaflet-geoman.js"></script>

ES6模块引入:

import * as L from "leaflet";
import "leaflet/dist/leaflet.css";
import "@geoman-io/leaflet-geoman-free";
import "@geoman-io/leaflet-geoman-free/dist/leaflet-geoman.css";

10、Leaflet.draw:通过一个非常漂亮的带有图标和提示的用户友好界面,实现了多段线、多边形、矩形、圆和标记等绘图功能。

11、leaflet-easyPrint:一个简单的插件,它添加了一个图标来打印你的 Leaflet 地图。

示例: https://rowanwins.github.io/leaflet-easyPrint/

在这里插入图片描述
leaflet—地图操作—导出成图片

在这里插入图片描述

12、Leaflet-Semicircle: 为 L.Circle 添加了绘制半圆的功能

示例: https://jieter.github.io/Leaflet-semicircle/examples/semicircle.html

https://jieter.github.io/Leaflet-semicircle/examples/semicircle.html

安装和使用:

npm i leaflet-semicircle
import "leaflet-semicircle";

/**
* []  坐标
* radius 半径
* startAngle  开始角度
* endAngle  结束角度
* fill 填充
* fillColor  填充色
* fillOpacity  填充透明度
*/
L.semiCircle([51.5, -0.09], {
    radius: 500,
	startAngle: 45,
	stopAngle: 135,
	fill: true,
    fillColor:'#f03',
    fillOpacity: 0.5,
    color: '#f03',
    opacity: 0.5,
}).addTo(map);

在这里插入图片描述
参考: 探索地图新维度:Leaflet-Semicircle

在这里插入图片描述

13、leaflet-velocity: 用 Leaflet 观察 velocity 图层

leaflet-velocity: 该库的核心功能是解析气象数据,特别是来自 GDAS (Global Data Assimilation System) 或其他类似提供动态流数据服务的 API。它能够将这些时间序列数据转换成可视化的层,让你可以直观地看到风向、速度或任何其他随时间变化的现象。

常用于实现风场动态粒子效果。

应用场景

Leaflet-Velocity 能用于:

  • 天气预报应用 - 显示风向、风速和其他气候变量的变化。
  • 环境监测 - 监控海洋流动、空气污染扩散等。
  • 航海与航空 - 提供实时的导航辅助信息。
  • 科研可视化 - 在地图上呈现气候变化模型或其他动态地理数据。
  • 教育与演示 - 为教学材料增添互动元素,使复杂的地理现象更易理解。

特点

  • 兼容性好 - 与 Leaflet 兼容,适应各种浏览器和设备。
  • 高性能 - 利用矢量瓦片技术,仅加载可视区域的数据,降低内存和带宽需求。
  • 自定义丰富 - 支持颜色映射、动画速度控制等多种设置,满足个性化需求。
  • 简单易用 - 简单的 API 设计,让集成到现有项目中变得容易。
  • 开源社区支持 - 持续更新和完善,社区活跃,有问题可以寻求帮助。

安装:

npm install leaflet
npm install leaflet-velocity

引用:

import "leaflet/dist/leaflet.css";
import L from "leaflet";
import "leaflet.chinatmsproviders";
import "leaflet-velocity/dist/leaflet-velocity.css";
import "leaflet-velocity/dist/leaflet-velocity";

使用示例:加载风场粒子效果

// 加载风场数据
    initWind() {
      axios
        .get("https://tf.istrongcloud.com/data/gfs/gfs.json")
        .then(({ data }) => {
          const arr = [];
          for (const i in data) {
            arr.push(data[i]);
          }
          this.windData = arr[0];

          velocityLayer = L.velocityLayer({
            displayValues: false,
            displayOptions: {
              velocityType: "GBR Wind",
              displayPosition: "bottomleft",
              displayEmptyString: "No wind data",
            },
            data: this.windData,
            // choseValue: "aqi",
            minVelocity: 0,
            maxVelocity: 15,
            velocityScale: 0.012,
            // particleMultiplier: 1 / 1200, //粒子的数量
            lineWidth: 2, //粒子的粗细
            frameRate: 15, //定义每秒执行的次数
            colorScale:  ["rgb(255, 255, 255)",
          				  "rgb(255, 255, 255)",
            			  "rgb(255, 255, 255)",
          			      "rgb(255, 255, 255)",
          				  "rgb(255, 255, 255)",
        				],
          });

          velocityLayer.addTo(maps);
          this.mapWindDisabled = false;
        });
    },

14、Leaflet Measure Path : 显示路径上的测量值; 当前支持折线、多边形和圆

Leaflet Measure Path: https://www.npmjs.com/package/leaflet-measure-path

demo示例: https://prominentedge.com/leaflet-measure-path/
在这里插入图片描述
安装:

npm i leaflet-measure-path

引用:

import "leaflet/dist/leaflet.css";
import L from "leaflet";
import 'leaflet-measure-path/leaflet-measure-path.css'
import 'leaflet-measure-path/leaflet-measure-path.js'

使用:

显示测量值:

var polygon = L.polygon([ ... ])
    .addTo(map)
    .showMeasurements();

隐藏测量值:

var polygon = L.polygon([ ... ])
    .addTo(map)
    .hideMeasurements();

在这里插入图片描述

15、Leaflet.TileLayer.ColorFilter:一个简单轻量级的 Leaflet 插件,用于在地图图块上应用 CSS 过滤器

安装:

npm install --save leaflet.tilelayer.colorfilter

引入:

import "leaflet/dist/leaflet.css";
import L from "leaflet";
import "leaflet.tilelayer.colorfilter";

使用:

let map = L.map('map').setView([51.505, -0.09], 14);

let myFilter = [
    'blur:0px',
    'brightness:95%',
    'contrast:130%',
    'grayscale:20%',
    'hue:290deg',
    'opacity:100%',
    'invert:100%',
    'saturate:300%',
    'sepia:10%',
];

let myTileLayer = L.tileLayer.colorFilter('https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png', {
    attribution: '<a href="https://wikimediafoundation.org/wiki/Maps_Terms_of_Use">Wikimedia</a>',
    filter: myFilter,
}).addTo(map);

使用天地图:

http://t0.tianditu.gov.cn/DataServer?T=vec_c&x={x}&y={y}&l={z}&tk=你的key

在这里插入图片描述

参考: leaflet【九】使用天地图&改变地图底色

滤镜:

CSS的滤镜功能是通过filter属性实现的,该属性提供了多种不同的视觉效果,用于改变网页元素的外观。这些效果包括模糊、亮度调整、对比度调整、灰度转换、色相旋转等。

CSS中的滤镜功能主要通过filter属性实现,该属性包含多种函数,每个函数对应不同的视觉效果。具体如下:

  • 模糊: 通过blur()函数实现,可以设置高斯模糊效果,使图像或元素看起来模糊。例如,filter: blur(5px);会使元素模糊5像素
  • 亮度: 使用brightness()函数调整,值范围从0%(全黑)到100%(无变化),超过100%的值也可以使图像更亮。例如,filter: brightness(200%);会使元素亮度加倍。
  • 对比度: 通过contrast()函数调整,值范围也是0%到100%,超过100%意味着更低的对比度。例如,filter: contrast(200%);会使元素对比度提高两倍。
  • 灰度: 使用grayscale()函数将图像转换为灰度图,100%值完全转为灰度图像,0%则无变化。例如,filter: grayscale(100%);将图像转换为黑白。
  • 色相旋转: 通过hue-rotate()函数应用,值表示色环角度,如hue-rotate(90deg)将图像色相旋转90度。
  • 反色: 使用invert()函数实现颜色反转效果,100%值完全反转颜色,0%则无变化。例如,filter: invert(1);会将元素的颜色完全反转。
  • 阴影: 通过drop-shadow()函数为元素添加阴影效果,可以设置阴影偏移、模糊度和颜色。例如,filter: drop-shadow(4px 4px 10px black);为元素添加了阴影。
  • 透明度: 使用opacity()函数调整元素的透明度,百分比值控制透明程度。例如,filter: opacity(50%);使元素50%透明。
  • 饱和度: 通过saturate()函数调整图像的饱和度,0%完全不饱和,100%无变化,超过100%增加饱和度。例如,filter: saturate(200%);会使图像饱和度加倍。
  • 褐色: 使用sepia()函数将图像转换为深褐色,100%完全转换为褐色,0%无变化。例如,filter: sepia(100%);将图像完全转换为深褐色。

在这里插入图片描述

16、leaflet-polycolor : 给每个多线段着色

前置知识: 在Leaflet中点对象使用SVG和Canvas两种模式的对比

在这里插入图片描述

官方示例Demo: https://oliv.github.io/leaflet-polycolor/

安装:

npm install --save leaflet-polycolor

使用:

ES6:

import L from 'leaflet';
import leafletPolycolor from 'leaflet-polycolor';
leafletPolycolor(L);

const map = L.map('map', {
    center: [45.1834782, 5.7831946],
    zoom: 13,
    preferCanvas: true,  // 重点
});

L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar'}).addTo(map);

const latLngs = [[45.187273, 5.758124], [45.182772, 5.758516], [45.185767, 5.747106], [45.176569, 5.752082], [45.171863, 5.757120], [45.168354, 5.755178]];
const colors = ['rgb(20, 200, 100)', 'rgb(200, 100, 20)', null, null, 'rgb(20, 200, 100)', 'rgb(0, 0, 0)'];

const polyline = L.polycolor(latLngs, {
  colors: colors,
  useGradient: true,
  weight: 5
}).addTo(map);

在这里插入图片描述

17、Leaflet.ellipse:通过指定中心点、半长轴、半短轴和向西倾斜的角度在地图上绘制椭圆

Demo 示例地址: https://jdfergason.github.io/Leaflet.Ellipse/

在这里插入图片描述

安装:

npm install leaflet-ellipse

使用:

import "leaflet/dist/leaflet.css";
import L from "leaflet";
import "leaflet-ellipse";

 let ellipse1 = L.ellipse([27.497730661009353, 111.68944804903713], [1000, 30], 45, {
 	color: "red",
 });
 let ellipse2 = L.ellipse([27.488190963817143, 111.70020006956051], [2500, 100], 45, {
 	color: "yellow",
    // fillPattern: stripes,
    fillOpacity: 0,
});
this.maps.addLayer(ellipse1);
this.maps.addLayer(ellipse2);

在这里插入图片描述

18、Leaflet.pattern:添加对路径上的图案填充的支持

安装:

npm install leaflet.pattern

使用:

import "leaflet/dist/leaflet.css";
import L from "leaflet";
import "leaflet.pattern/dist/leaflet.pattern";

var stripes = new L.StripePattern({
	weight: 5,
    spaceWeight: 5,
    // color: "#ffff00",
    // spaceColor: "#ffff00",
    opacity: 1,
    spaceOpacity: 0,
});
stripes.addTo(this.maps);

var circle = new L.Circle([27.50409, 111.682279], 400.0, {
	fillPattern: stripes,
    stroke: false,
    fillOpacity: 0.5,
});
circle.addTo(this.maps);

在这里插入图片描述
在这里插入图片描述

19、Leaflet-CanvasMarker:在 Canvas 而不是 DOM 上显示标记

参考:leaflet如何加载10万条数据

Leaflet-CanvasMarker:Leaflet.Canvas-Markers的改进版本

Leaflet.Canvas-Markers:这个插件有个问题,就是地图缩放时,添加的数据不跟着同步缩放,而是等到缩放完成后,再去缩放。这样感觉缩放时,数据在飘着。

Leaflet-CanvasMarker 插件描述: 在Canvas上绘制Marker,而不是每个marker插件一个dom节点,极大地提高了渲染效率。主要代码参考自 https://github.com/eJuke/Leaflet.Canvas-Markers ,不过此插件有些Bug,github国内不方便,作者也不维护了,所以在gitee上新建一个仓库进行维护与升级。

npm下载

npm i @panzhiyue/leaflet-canvasmarker

使用

import {CanvasMarkerLayer} from "@panzhiyue/leaflet-canvasmarker"

示例

// 创建图层
var ciLayer = L.canvasMarkerLayer({
  collisionFlg: true
}).addTo(map);

var icon = L.icon({
  iconUrl: 'img/pothole.png',
  iconSize: [20, 18],
  iconAnchor: [10, 9]
});
// 定义Marker
var markers = [];
for (var i = 0; i < 100000; i++) {
  var marker = L.marker([58.5578 + Math.random() * 1.8, 29.0087 + Math.random() * 3.6], {
    icon: icon,
    zIndex: 2
  }).bindPopup("I Am " + i);
  markers.push(marker);
}
// 把marker添加到图层
ciLayer.addLayers(markers);
//定义事件
ciLayer.addOnClickListener(function (e, data) {
  console.log(data)
});
ciLayer.addOnHoverListener(function (e, data) {
  console.log(data[0].data._leaflet_id)
});

在这里插入图片描述

20、Leaflet.markercluster:美丽、复杂、高性能的标记聚类解决方案,具有流畅的动画和许多强大的功能。 推荐!

在这里插入图片描述
中文文档: Leaflet.markercluster 中文文档 V1.5.4

官网: Documentation - Leaflet - 一个交互式地图 JavaScript 库

处理大量标记的示例:

该插件可以处理10,000 甚至 50,000 个标记 (在chrome浏览器下). IE9 在 50,000 数量下会存在一些问题。

(1)真实地图10,000标记案例

(2)真实地图50,000标记案例

下载

使用unpkg的CDN: https://unpkg.com/leaflet.markercluster@1.4.1/dist/
在这里插入图片描述

通过npm命令安装: npm install leaflet.markercluster

npm install leaflet.markercluster

对应自身情况,请斟酌引用 dist 目录下的文件:

  • MarkerCluster.css
  • MarkerCluster.Default.css (如果你要使用自定义的iconCreateFunction而不是默认的函数,则不需要引入)
  • leaflet.markercluster.js (或者引入未压缩版本 leaflet.markercluster-src.js )

引入

  <!-- 引入 Leaflet.markercluster 相关依赖-->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.5.3/MarkerCluster.css"
    integrity="sha512-mQ77VzAakzdpWdgfL/lM1ksNy89uFgibRQANsNneSTMD/bj0Y/8+94XMwYhnbzx8eki2hrbPpDm0vD0CiT2lcg=="
    crossorigin="anonymous" referrerpolicy="no-referrer" />
  <link rel="stylesheet"
    href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.5.3/MarkerCluster.Default.css"
    integrity="sha512-6ZCLMiYwTeli2rVh3XAPxy3YoR5fVxGdH/pz+KMCzRY2M65Emgkw00Yqmhh8qLGeYQ3LbVZGdmOX9KUjSKr0TA=="
    crossorigin="anonymous" referrerpolicy="no-referrer" />
  <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.5.3/leaflet.markercluster.js"
    integrity="sha512-OFs3W4DIZ5ZkrDhBFtsCP6JXtMEDGmhl0QPlmWYBJay40TT1n3gt2Xuw8Pf/iezgW9CdabjkNChRqozl/YADmg=="
    crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  <!-- <link rel="stylesheet" href="https://unpkg.com/browse/leaflet.markercluster@1.4.1/dist/MarkerCluster.css">
  <link rel="stylesheet" href="https://unpkg.com/browse/leaflet.markercluster@1.4.1/dist/MarkerCluster.Default.css">
  <script src="https://unpkg.com/browse/leaflet.markercluster@1.4.1/dist/leaflet.markercluster.js"></script> -->

// 引入 leaflet.markercluster  聚合插件
import "leaflet.markercluster/dist/MarkerCluster.css"
import "leaflet.markercluster/dist/MarkerCluster.Default.css"
import "leaflet.markercluster";

使用

通过聚合分组的方案也可以满足加载大量数据不卡顿,下面是使用案例,创建了十万个点渲染到页面上。

import 'leaflet.markercluster/dist/leaflet.markercluster';
import 'leaflet.markercluster/dist/MarkerCluster.css';
import 'leaflet.markercluster/dist/MarkerCluster.Default.css';

const addCluster = () => {
  const clusterLayer = L.markerClusterGroup({
    // showCoverageOnHover: false,
    // zoomToBoundsOnClick: false,
    // spiderfyOnMaxZoom: false,
    // removeOutsideVisibleBounds: false,
    // spiderLegPolylineOptions: {}
    // 自定义聚合样式
    // iconCreateFunction: function (cluster) {
    // return L.divIcon({html: '<b class="bg-#[f40]">' + cluster.getChildCount() + '</b>'});
    // }
  });
  for (let i = 0; i < 100000; i++) {
    const marker = L.marker([18.8567 + Math.random(), 102.3508 + Math.random()], {
      title: `${i}`,
      icon: L.icon({
        iconUrl: Money,
        iconSize: [20, 20],
        iconAnchor: [0, 0]
      })
    });
    marker.on('click', function (event) {
      console.log('marker ====', event.latlng);
    });

    marker.on('clusterclick', function (a) {
      // a.layer is actually a cluster
      console.log('cluster ' + a.layer.getAllChildMarkers().length);
    });
    clusterLayer.addLayer(marker);
  }
  map.addLayer(clusterLayer);
};

在这里插入图片描述

markerClusterGroup配置对象

属性/方法说明
showCoverageOnHover将鼠标悬停在集群上时,它会显示其标记的边界
zoomToBoundsOnClick单击集群时,会缩放到其边界
spiderfyOnMaxZoom当您单击底部缩放级别的集群时,我们会对其进行蜘蛛化,以便您可以查看其所有标记
removeOutsideVisibleBounds为了提高性能,将从地图中删除离视口太远的聚类和标记
spiderLegPolylineOptions允许您指定 PolylineOptions 来设置蜘蛛腿的样式。默认情况下,它们是 { weight: 1.5, color: ‘#222’, opacity: 0.5 }
animate在缩放和蜘蛛化时平滑拆分/合并集群子项
iconCreateFunctionFn,自定义聚合样式
spiderfyShapePositionsFn,覆盖蜘蛛形状位置

21、Leaflet.PolylineDecorator:允许你沿着折线或坐标路径绘制图案(如破折号、箭头或均匀间隔的标记)

访问地址https://gitcode.com/gh_mirrors/le/Leaflet.PolylineDecorator
在这里插入图片描述
示例 Demo

https://bbecquet.github.io/Leaflet.PolylineDecorator/example/example.html
在这里插入图片描述

下载

npm i leaflet-polylinedecorator

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Leaflet.PolylineDecorator - 允许你沿着折线或坐标路径绘制图案(如破折号、箭头或均匀间隔的标记)</title>

  <link rel="stylesheet" href="./js/leaflet.css" />
  <script src="./js/leaflet.js"></script>
  <script src="./js/leaflet.polylineDecorator.js"></script>

  <style>
    html,
    body {
      width: 100%;
      height: 100%;
      padding: 0;
      margin: 0;
    }

    .map-box {
      width: 100%;
      height: 100%;
    }
  </style>
</head>

<body>
  <div class="map-box" id="leafletMapService"></div>

  <script>
    // 加载天地图矢量图层
    let tdtVecW = L.tileLayer(
      "https://t0.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=你的天地图key"
    );

    // 加载天地图矢量注记图层
    let tdtCvaW = L.tileLayer(
      "https://t0.tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=你的天地图key"
    );

    let maps = L.map('leafletMapService', {
      // center: [27.50409, 111.682279],
      center: [52.0, -11.0],
      zoom: 5,
      minZoom: 3,
      maxZoom: 18,
      zoomControl: true,  // 是否隐藏左上角的缩放
      attributionControl: false, // 是否隐藏右下角的信息显示
      layers: [tdtVecW, tdtCvaW]
    });

    /**
     * Pattern definition
     * 
     * offset:(可选)第一个图案符号与线条起点的偏移量。默认值:0。
     * endOffset:(可选)最后一个图案符号与线条终点的最小偏移量。默认值:0。
     * repeat:(必填)图案符号的重复间隔。定义每个连续符号锚点之间的距离。
     * symbol:(必填)符号工厂类的实例。是如何绘制每一段的定义,比如使用L.Symbol.dash, L.Symbol.arrowHead等
     * 
     * offset、endOffset 和 repeat 可以分别定义为以像素为单位的数字,或以字符串为单位的行长百分比(例如:"10%")。
     */

    // --- Simple arrow ---
    let arrow = L.polyline([[57, -19], [60, -12]], {}).addTo(maps);
    // 箭头
    let arrowHead = L.polylineDecorator(arrow, {
      patterns: [
        {
          offset: '100%',
          repeat: 2,
          symbol: L.Symbol.arrowHead({
            pixelSize: 15,
            polygon: false,
            pathOptions: { stroke: true }
          })
        }
      ]
    }).addTo(maps);


    // --- Polygon, with an inner ring ---
    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: 1 }).addTo(maps);
    let pd = L.polylineDecorator(polygon, {
      patterns: [
        { offset: 0, repeat: 10, symbol: L.Symbol.dash({ pixelSize: 0 }) }
      ]
    }).addTo(maps);

    // --- Multi-pattern without Polyline ---
    var pathPattern = L.polylineDecorator(
      [[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], [49.860606, -15.414253], [49.672607, -15.710152], [49.863344, -16.451037], [49.774564, -16.875042], [49.498612, -17.106036], [49.435619, -17.953064], [49.041792, -19.118781], [48.548541, -20.496888], [47.930749, -22.391501], [47.547723, -23.781959], [47.095761, -24.941630], [46.282478, -25.178463], [45.409508, -25.601434], [44.833574, -25.346101], [44.039720, -24.988345]],
      {
        patterns: [
          { offset: 12, repeat: 25, symbol: L.Symbol.dash({ pixelSize: 10, pathOptions: { color: '#f00', weight: 2 } }) },
          { offset: 0, repeat: 25, symbol: L.Symbol.dash({ pixelSize: 0 }) }
        ]
      }
    ).addTo(maps);

    // --- Markers proportionnaly located ---
    var markerLine = L.polyline([[58.44773, -28.65234], [52.9354, -23.33496], [53.01478, -14.32617], [58.1707, -10.37109], [59.68993, -0.65918]], { color: '#ff0000', weight: 10 }).addTo(maps);
    var markerPatterns = L.polylineDecorator(markerLine, {
      patterns: [
        {
          offset: '5%', repeat: '25%', symbol: L.Symbol.marker({
            rotate: true,
            markerOptions: {
              icon: L.icon({
                // iconUrl: 'icon_plane.png',
                iconUrl: './imgs/icon_plane.png',
                iconAnchor: [16, 16]
              })
            }
          })
        }
      ]
    }).addTo(maps);

    // 绘制带箭头的线条(路径)
    let arrowLine = L.polylineDecorator(markerLine, {
      patterns: [
        {
          offset: 30,   // 箭头起始位置距离线条两端的距离
          repeat: 60,  // 箭头重复的间隔
          symbol: L.Symbol.arrowHead({
            pixelSize: 5,  // 箭头大小
            headAngle: 75,  // 角度
            polygon: false,
            pathOptions: { stroke: true, weight: 4, color: '#fff' }
          })
        }
      ]
    }).addTo(maps);

    // --- Example with a rotated marker ---
    var pathPattern = L.polylineDecorator(
      [[42.9, -15], [44.18, -11.4], [45.77, -8.0], [47.61, -6.4], [49.41, -6.1], [51.01, -7.2]],
      {
        patterns: [
          { offset: 0, repeat: 10, symbol: L.Symbol.dash({ pixelSize: 5, pathOptions: { color: '#000', weight: 1, opacity: 0.2 } }) },
          {
            offset: '16%', repeat: '33%', symbol: L.Symbol.marker(
              {
                rotate: true,
                markerOptions: {
                  icon: L.icon({
                    // iconUrl: 'icon_plane.png',
                    iconUrl: './imgs/icon_plane.png',
                    iconAnchor: [16, 16]
                  })
                }
              }
            )
          }
        ]
      }
    ).addTo(maps);

    // --- Example with an array of Polylines ---
    var 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]]
    ];
    var plArray = [];
    for (var i = 0; i < multiCoords1.length; i++) {
      plArray.push(L.polyline(multiCoords1[i]).addTo(maps));
    }
    L.polylineDecorator(multiCoords1, {
      patterns: [
        { offset: 25, repeat: 50, symbol: L.Symbol.arrowHead({ pixelSize: 15, pathOptions: { fillOpacity: 1, weight: 0 } }) }
      ]
    }).addTo(maps);
  </script>

</body>

</html>
引用\[1\]中提到了清空测绘图层和取消监听方法的代码片段,但是没有提到具体的Leaflet测距插件。在Leaflet中,有一个常用的测距插件叫做Leaflet.MeasureControl。这个插件可以用于在地图上进行距离和面积的测量。你可以通过引入该插件的库文件,并在地图上添加相应的控件来实现测距功能。 以下是一个使用Leaflet.MeasureControl插件的示例代码: ```javascript // 引入LeafletLeaflet.MeasureControl库文件 import L from 'leaflet'; import 'leaflet-measure'; // 创建地图实例 const map = L.map('map'); // 添加底图图层 const tileLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors', }).addTo(map); // 添加测距控件 const measureControl = new L.Control.Measure({ position: 'topright', primaryLengthUnit: 'meters', secondaryLengthUnit: 'kilometers', primaryAreaUnit: 'sqmeters', secondaryAreaUnit: 'hectares', }); measureControl.addTo(map); ``` 在上述代码中,我们首先引入了LeafletLeaflet.MeasureControl库文件。然后创建了一个地图实例,并添加了一个底图图层。接下来,我们创建了一个测距控件实例,并设置了控件的位置和单位。最后,将测距控件添加到地图上。 通过以上代码,你可以在Leaflet地图上使用测距插件进行距离和面积的测量。请注意,你需要根据自己的项目需求进行相应的配置和样式调整。 #### 引用[.reference_title] - *1* [如何在React和Vue框架中实现leafLet.js测距和测面工具](https://blog.youkuaiyun.com/weixin_44733660/article/details/120173108)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值