LeafLet加载自定义Legend的设计与实现

news2024/12/26 10:56:01

背景

        众所周知,在GIS的世界里,图例和地图永远是一对一起出现的对象。在地图上表示地理环境各要素,比如山脉、河流、城市、铁路等所用的符号叫做图例。这些符号所表示的意义,常注明在地图的边角上。图例是表达地图内容的基本形式和方法,是现代地图的语言,是读图和用读所借助的工具。地图符号一般包括各种大小、粗细、颜色不同的点、线、图形等。符号的设计要能表达地面景物的形状、大小和位置,而且还能反映出各种景物的质和量的特征,以及相互关系。因此图例常设计成与实地景物轮廓相似的几何图形。

         还有一些地图,专门表示各种自然条件、工业分布等。在这些图上,也必然有相应的图例,说明某种符号代表某种森林,某种符号代表某种矿产,某种符号代表某种工业,等等。读图之前,先把图例中的地图符号和注记的意义弄清楚,对于正确理解地图内容就方便多了。可以这样说,图例是读图的“线索”,方便用户按图索骥。

         在之前的博文中,介绍了很多Leaflet的内容,关于图例的展示一直没有涉及。本文简单讲讲在Leaflet中如何进行图例的展示,基于Leaflet.Legend进行图例的展示。通过讲解Leaflet.Legend得集成,核心API的讲解,让您对Leaflet.Legend有一个基本的认识和了解。

一、Leaflet.Legend简介

        Leaflet本身是一个非常轻量级的前端组件,基于Leaflet有很多的扩展插件,围绕Leaflet的生态非常丰富。在Leaflet中的插件中,可以找到下面的插件列表内容。

 1、Legend的开源协议

        Leaflet.Legend是一个MIT协议,非常宽松的协议。可放心在项目中使用。Leaflet.Legend 是一个 Leaflet 插件, 用于显示图例符号和切换相应的叠加层的显示.开源地址:Legend。

MIT License

Copyright (c) 2020 ptma@163.com

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

 2、Legend API介绍

        打开src目录下的leaflet.legend.js文件,这里是整个图例类的源码文件,如上图所示的各个Symbol类都定义在这里。下面就这些类进行深入的讲解。

options: {
            position: "topleft",
            title: "Legend",
            legends: [],
            symbolWidth: 24,
            symbolHeight: 24,
            opacity: 1.0,
            column: 1,
            collapsed: false,
        },

        initialize: function (options) {
            L.Util.setOptions(this, options);
            this._legendSymbols = [];
            this._buildContainer();
        },

        上述代码定义了创建图例对象的各个属性,具体的参数说明如下:

参数名称类型默认值描述 
positionStringtopleft图例控件位置
titleStringLegend图例控件的标题
opacityNumber1.0图例面板的透明度
legendsLegendSymbol[][][LegendSymbol](#legendsymbol) 图例符号数组。
symbolWidthNumber24图例符号的宽度,以像素为单位
symbolHeightNumber24图例符号的高度,以像素为单位
columnNumber1图例符号排列的列数
collapsedBooleanfalse图例面板是否默认展开

        LegendSymbol对象的定义如下:

参数名称类型默认值描述
labelStringundefined图例符号的文本标签。
typeStringundefined图例符号的类型. 可以是image','circle','rectangle','polygon' 或 'polyline'。
urlStringundefined图里图片的 URL,仅用于 type 为 'image' 时
radiusNumberundefined圆形图例的半径,以像素为单位,仅用于 type 为 'circle' 时
sidesNumberundefined正多边形的边数,仅用于 type 为 'polygon' 时。
layersLayerLayer[]undefined,图例符号关联的叠加层. 关联叠加层后可通过点击图例来切换相应叠加层的可见性。
inactiveBooleanundefined图例符号是否为非激活的, 非激活的图例会减淡显示
strokeBooleantrue是否绘制边框
colorString#3388ff边框颜色
weightNumber边框宽度
opacityNumber1.0边框透明度
lineCapStringround指定如何绘制每一条线段末端的属性。有 3 个可能的值,分别是:'butt','round' 或 ’square‘
lineJoinStringround用来设置2个长度不为0的相连部分(线段,圆弧,曲线)如何连接在一起的属性(长度为0的变形部分,其指定的末端和控制点在同一位置,会被忽略)
dashArrayStringnull控制用来描边的点划线的图案范式
dashOffsetStringnulldash模式到路径开始的距离
fillBooleandepends是否用颜色填充
fillColorString*填充色,默认与边框颜色相同
fillOpacityNumber0.2 填充透明度
fillRuleStringevenodd填充规则

二、Legend实例开发

        有了上面对图例API的基础认知之后,我们便可以进行相应的实例开发。下面将使用一个详细的案例讲解,来详细说明Legend如何进行深入开发。

1、新建html页面

<!DOCTYPE html>
<html>

<head>
    <title>Leaflet legend control</title>
    <meta charset="utf-8" />
    <style type="text/css">
        body {
            padding: 0;
            margin: 0;
        }

        html,
        body,
        #map {
            height: 100%;
        }

    </style>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
    <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>

    <link rel="stylesheet" href="../src/leaflet.legend.css" />
    <script type="text/javascript" src="../src/leaflet.legend.js"></script>
</head>

<body>
    <div id="map"></div>
</body>
</html>

2、创建Leaflet对象引用

var map = L.map("map", {
    center: [29.797751134173065, 120.7012939453125],
    zoom: 5
});
	
L.tileLayer('file:///D%3A/wzh_test/q0403/{z}/{x}/{y}.png', {
    minZoom: 0,
    maxZoom: 7,
    tms: false,
    attribution: '图例功能测试-夜郎king'
}).addTo(map);

3、图例定义

var marker = L.circleMarker(L.latLng(29.702368038541767, 120.47607421874999), {
        radius: 6,
        fillColor: "#ff0000",
        color: "blue",
        weight: 2,
        opacity: 1,
        fillOpacity: 0.6,
    });

    var latlngs = [
        [
            29.204918463909035,
            119.6246337890625,
        ],
        [
            29.79358002272772,
            120.27008056640624,
        ],
        [
            29.70087695780884,
            120.2984046936035,
        ]
    ];
    var polyline = L.polyline(latlngs, {
        color: 'red'
    }).addTo(map);

    const legend = L.control.Legend({
            position: "bottomleft",
            collapsed: false,
            symbolWidth: 24,
            opacity: 1,
			title:"图例",
            column: 2,
            legends: [{
                label: "位置",
                type: "image",
                url: "marker/marker-red.png",
            }, {
                label: "Marker2",
                type: "image",
                url: "marker/purple.png"
            }, {
                label: "Circle",
                type: "circle",
                radius: 6,
                color: "blue",
                fillColor: "#FF0000",
                fillOpacity: 0.6,
                weight: 2,
                layers: [marker],
                inactive: true,
            }, {
                label: "Real line",
                type: "polyline",
                color: "#FF0000",
                fillColor: "#FF0000",
                weight: 2,
                layers: polyline
            }, {
                label: "Dotted line",
                type: "polyline",
                color: "#0000FF",
                fillColor: "#0000FF",
                dashArray: [5, 5],
                weight: 2
            }, {
                label: "Rectangle",
                type: "rectangle",
                color: "#FF0000",
                fillColor: "#FF0000",
                weight: 2
            }, {
                label: "Square",
                type: "polygon",
                sides: 4,
                color: "#FF0000",
                fillColor: "#FF0000",
                weight: 2
            }, {
                label: "Regular triangle",
                type: "polygon",
                sides: 3,
                color: "#FF0000",
                fillColor: "#FF0000",
                weight: 2
            }, {
                label: "Regular polygon",
                type: "polygon",
                sides: 5,
                color: "#FF0000",
                fillColor: "#FF0000",
                weight: 2
            }]
        })
        .addTo(map);

4、展示效果

         点击Circle图例还可以进行图层的切换,默认情况下,地图上不展示这些信息,点击之后会在地图上添加相应的图层对象。

5、图例调用过程

        在源码中进行debug调试,观察相应的代码如何执行的。首先进行Legend初始化,调用initialize方法,在这个方法中会将出入的参数进行解析,然后再创建元素对象。

_buildContainer: function () {
            this._container = L.DomUtil.create("div", "leaflet-legend leaflet-bar leaflet-control");
            this._container.style.backgroundColor = "rgba(255,255,255, " + this.options.opacity + ")";

            this._contents = L.DomUtil.create("section", "leaflet-legend-contents", this._container);
            this._link = L.DomUtil.create("a", "leaflet-legend-toggle", this._container);
            this._link.title = "Legend";
            this._link.href = "#";

            var title = L.DomUtil.create("h3", "leaflet-legend-title", this._contents);
            title.innerText = this.options.title || "Legend";

            var len = this.options.legends.length;
            var colSize = Math.ceil(len / this.options.column);
            var legendContainer = this._contents;
            for (var i = 0; i < len; i++) {
                if (i % colSize == 0) {
                    legendContainer = L.DomUtil.create("div", "leaflet-legend-column", this._contents);
                }
                var legend = this.options.legends[i];
                this._buildLegendItems(legendContainer, legend);
            }
        },

         在上面的代码执行过程中定义相应的图例对象,同时将对象放置到页面元素中。下面重点看一下各个图例对象是怎么进行初始化的。

_buildLegendItems: function (legendContainer, legend) {
            var legendItemDiv = L.DomUtil.create("div", "leaflet-legend-item", legendContainer);
            if (legend.inactive) {
                L.DomUtil.addClass(legendItemDiv, "leaflet-legend-item-inactive");
            }
            var symbolContainer = L.DomUtil.create("i", null, legendItemDiv);

            var legendSymbol;
            if (legend.type === "image") {
                legendSymbol = new ImageSymbol(this, symbolContainer, legend);
            } else if (legend.type === "circle") {
                legendSymbol = new CircleSymbol(this, symbolContainer, legend);
            } else if (legend.type === "rectangle") {
                legendSymbol = new RectangleSymbol(this, symbolContainer, legend);
            } else if (legend.type === "polygon") {
                legendSymbol = new PolygonSymbol(this, symbolContainer, legend);
            } else if (legend.type === "polyline") {
                legendSymbol = new PolylineSymbol(this, symbolContainer, legend);
            } else {
                L.DomUtil.remove(legendItemDiv);
                return;
            }
            this._legendSymbols.push(legendSymbol);

            symbolContainer.style.width = this.options.symbolWidth + "px";
            symbolContainer.style.height = this.options.symbolHeight + "px";

            var legendLabel = L.DomUtil.create("span", null, legendItemDiv);
            legendLabel.innerText = legend.label;
            if (legend.layers) {
                L.DomUtil.addClass(legendItemDiv, "leaflet-legend-item-clickable");
                L.DomEvent.on(
                    legendItemDiv,
                    "click",
                    function () {
                        this._toggleLegend.call(this, legendItemDiv, legend.layers);
                    },
                    this
                );
            }
        },

 以上就是Legend图例对象的主要执行过程,有兴趣的朋友可以把源码clone到本地进行深入研究。

总结

        以上就是本文的主要内容,本文简单讲解在Leaflet中如何进行图例的展示。通过讲解Leaflet.Legend的集成,核心API的讲解,让您对Leaflet.Legend有一个基本的认识和了解。本文行文仓促,难免有误,欢迎批评指正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/453887.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

引用与指针:在C++中如何做出正确的选择?

文章目录 前言1. 引用入门2. 引用作为函数传参3. 引用作为函数返回值4. 引用和指针5. 其他区别 前言 引用是 C 的新增内容&#xff0c;在实际开发中会经常使用&#xff0c;它就如同C语言的指针一样重要&#xff0c;但它比指针更加方便和易用&#xff0c;有时候甚至是不可或缺的…

使用YOLOV5-6.2预训练模型(yolov5s)进行detect的详细说明(detect.py)文件解析

目录 准备源文件和预训练文件下载python版本以及torch版本说明&#xff1a;文件目录说明测试文件 detect.py使用测试单张图片测试一个文件夹里的图片 准备 源文件和预训练文件下载 下载链接&#xff1a;https://github.com/ultralytics/yolov5/releases/tag/v6.2 源文件和预训…

数据科学与机器学习在软件开发中的应用

数据科学和机器学习是现代软件开发的重要组成部分&#xff0c;可以帮助开发人员更好地理解和分析数据&#xff0c;从而提高软件的质量和性能。在本篇博客中&#xff0c;我将深入探讨数据科学和机器学习在软件开发中的应用&#xff0c;并讨论它们如何帮助我们创建更好的软件。 …

你最想知道的APP自动化测试项目实战详解

目录 一、引言 二、APP自动化测试的基本概念 三、APP自动化测试的流程 四、APP自动化测试的最佳实践 五、常见的APP自动化测试工具 六、APP自动化测试的挑战和解决方案 七、结论 一、引言 随着移动设备的普及和应用市场的繁荣&#xff0c;越来越多的企业开始开发和发布移…

【手撕MyBatis源码】执行器与缓存

文章目录 概述执行器(Executor)执行器总结 缓存MyBatis缓存概述一级缓存(LocalCache)Spring集成MyBatis后一级缓存失效的问题二级缓存二级缓存组件结构二级缓存的使用为什么要提交之后才能命中二级缓存?二级缓存结构二级缓存执行流程 概述 通过一条修改语句&#xff0c;我们来…

Android 开发死磕性能优化,方向是否正确?

在 Android 开发者技能中&#xff0c;如果想进大厂&#xff0c;一般拥有较好的学历可能有优势一些。 但是如果你靠硬实力也是有机会的&#xff0c;例如死磕性能优化&#xff0c;成为一名Android性能优化的高手&#xff0c;也算是目前招聘过程中比较稀缺的人才&#xff0c;可以…

Maven安装及其原理

一、maven安装 maven 3.6.1的安装包如下 二、配置本地仓库和阿里云私服 打开在上述百度网盘下载的文件&#xff0c;打开conf下面的setting.xml&#xff0c;大概第55行增加如下代码 &#xff0c;意思是指定一个目录为本地jar包的文件夹&#xff0c;管理jar包。一般来说&…

C++位图

位图 文章目录 位图setResetTest整体代码位图应用 给定40亿个不重复、没排序的无符号整数&#xff0c;再给一个无符号整数&#xff0c;如何快速判断一个数是否在这40亿个数中&#xff1f;&#xff1f;&#xff1f;首先想到的是归并排序二分查找。排序可以排&#xff0c;但是通过…

【计算机组成原理】第三章 存储系统

文章目录 知识体系3.1 存储器概述3.1.1 存储器的分类3.1.2 存储器的性能指标3.1.3 多级层次的存储系统 3.2 主存储器3.2.1 SRAM芯片和DRAM芯片3.2.2 只读存储器3.2.3 主存储器的基本组成3.2.4 多模块存储器 3.3 主存储器与CPU的连接3.3.1 连接原理3.3.2 主存容量的扩展3.3.3 存…

指定GPU运行python程序

一、命令行运行python程序时 1、首先查看哪些GPU空闲&#xff0c;nvidia-smi显示当前GPU使用情况。 nvidia-smiGPU&#xff1a;编号&#xff0c;这里是0和1 Fan&#xff1a;风扇转速&#xff0c;在0到100%之间变动&#xff0c;第一个是29% Name&#xff1a;显卡名&#xff…

布署到centos7.9时,ModuleNotFoundError: No module named ‘_sqlite3‘

先下载编译sqlite3 wget http://www.sqlite.org/sqlite-3.5.6.tar.gz cd sqlite-3.5.6 ./configure --disable-tcl make && make install 注意add LIBDIR to the ‘LD_LIBRARY_PATH’ environment variable&#xff0c;这是sqlite建议添加环境变量。 所以: echo expor…

「C/C++」C/C++异常处理

博客主页&#xff1a;何曾参静谧的博客 文章专栏&#xff1a;「C/C」C/C学习 目录 相关术语一、C语言中的异常处理1.返回值来传递错误信息2.使用标准库函数对异常进行处理&#xff08;不推荐&#xff09;3.使用全局变量来记录错误信息(不推荐) 二、C中的异常处理1.try{}catch()…

内外部函数静态变量全局变量

1、函数&#xff08;封装、复用&#xff09; 功能性&#xff1a;最基本的特性&#xff1b; 扩展性&#xff1a;对于时刻变化的需求易于扩展&#xff1b; 维护性&#xff1a;对于时刻变化的需求易于维护&#xff0c;易于编码变更&#xff1b; 封装性&#xff1a;不要把所有的代…

G1回收器:区域化分代式

G1回收器概述 既然我们己经有了前面几个强大的GC,为什么还要发布Garbage First(G1)GC? 原因就在于应用程序所应对的业务越来越庞大、复杂&#xff0c;用户越来越多&#xff0c;没有GC就不能保证应用程序正常进行&#xff0c;而经常造成STW的GC又跟不上实际的需求&#xff0c…

Python 实验四 常用数据结构(1)

1.从键盘输入一个正整数列表&#xff0c;以一1结束&#xff0c;分别计算列表中奇数和偶数的和。 n int(input("请输入一个正整数&#xff1a;")) list [] while n ! -1:list.append(n)n int(input("请输入一个正整数&#xff1a;")) else:print("…

Linux下C/C++实现(网络流量分析-NTA)

网络流量分析&#xff08;NTA - Network Traffic Analysis) 就是捕捉网络中流动的数据包&#xff0c;并通过查看包内部数据以及进行相关的协议、流量、分析、统计等&#xff0c;协助发现网络运行过程中出现的问题。通过监控和分析网络环境中的流量&#xff0c;来判断流量是用在…

electron编译环境搭建和第一个桌面应用例子

前言 Electron是基于Chromium和Node.js实现的&#xff0c;所以开发人员所需要使用到的前端技术主要包括以下方面&#xff1a; 1、Html、CSS、JavaScript、ES6 2、前端开发工具Vue、Angular、React等的一种 3、其他网络、缓存、通讯、系统、跟踪等前端技术 4、对Vscode编辑…

SpringCloud --- 认识微服务、服务拆分和远程调用

一、认识微服务 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢&#xff1f; 1.1、单体架构 单体架构&#xff1a;将业务的所有功能集中在一个项目中开发&#xff0c;…

C++学习(day5)

文章目录 一. 静态成员变量和函数(static)1. 静态成员变量2. 静态成员函数 二. 类的继承&#xff08;inhert&#xff09;1. 继承2. 继承的作用3. 一个类B继承类A4. 继承格式5. 子类会继承父类的所有成员6. 当父子类中出现同名的成员时7. **继承中构造函数和析构函数调用顺序**8…

反垃圾邮件产品测试评价方法示意图

声明 本文是学习信息安全技术 反垃圾邮件产品技术要求和测试评价方法. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 反垃圾邮件产品测试评价方法 测试环境 反垃圾邮件产品的典型测试环境如图1所示。 图1 反垃圾邮件产品典型测试环境示意图 测试设…