基于SpringBoot和Leaflet的行政区划地图掩膜效果实战

目录

前言

一、掩膜小知识

1、GIS掩膜的实现原理

2、图层掩膜流程 

二、使用插件

1、leaflet-mask介绍

2、核心代码解释 

三、完整实例实现

1、后台逻辑实现

2、省级行政区划查询实现

3、行政区划定位及掩膜实现 

4、成果展示

总结


前言

        在之前的博客提过按空间矢量范围下载遥感,有兴趣的同学可以参考已下的博文地址:基于QGIS的研究区域遥感影像裁切下载方法-以岳麓区为例。在这篇博客中采用的是Qgis软件,这是 一款桌面端的GIS软件。在这里,首先简单解释一下gis中掩膜的相关概念。掩膜在制图中是一种遮盖工具,用于处理要素在显示上的冲突。掩膜可以理解为一种看不见的面要素,它遮挡住了不需要显示的图形。用这个工具可以将影像按面要素周长裁剪。

        存在两种类型的掩膜策略:一是:图层掩膜 - 是指在地图或场景中,某一要素图层或掩膜图层可以掩盖另一图层中的任何重叠要素。二是要素级掩膜 - 是指按照两图层间关系类所指定的方式对各相关要素进行的掩膜。无论采用哪种掩膜方式,掩膜要素的几何均会掩盖被掩膜要素的符号系统。 即使掩膜要素的符号化形状与几何不同,(例如,如果应用了符号缓冲),要素几何的形状会进行掩膜。 然而,被掩膜要素的符号系统会受到影响。 被掩膜要素看起来可能存在孔洞,但它们只是可见符号中的孔洞。 要素几何并未更改。

        本文讲解的是一种图层级的掩膜,即使用行政区划图层来进行掩膜。使用场景为,用户只需要在地图页面中展示目标行政区划内的影像信息,对于行政边界外的影像,则不展示。这就是WebGIS中掩膜的一种表达方式。本文重点讲解在Webgis中如何进行行政区划掩膜实现,通过代码实战的方式对功能进行详细的实现,采用网友编写一个掩膜组件,不仅避免了自己的区域绘制太小,也避免了不同行政区划切换时,有部分缝隙的问题。如果您目前也有WebGIS掩膜可视化需求,不妨来看看博客。

一、掩膜小知识

        在讲解地图之前,如果了解前端的朋友一定知道,在HTML5的应用中,可能会存在两个DIV,可能由于其内容和位置的设置存在空间重叠,有一部分区域会被另一个DIV进行遮盖。这种效果就是掩膜。(以上不是官网的定义,只是翻译成了大白话,易于大家理解)。通过上面的解释可以看出,在这个场景中涉及的图层起码有两个,而且存在空间折叠的关系。而实现效果就是通过叠加,使用遮罩这种方式来进行。

1、GIS掩膜的实现原理

        与上述Html的实现原始一致的,在这个场景当中。首先我们会使用栅格底图(一般是遥感影像)。然后在展示行政区划时,自动将行政区划外的地图遮住。比如在展示湖南省的行政区划时,只展示湖南省区域内的影像,对于湖南省外的区域则不展示,以空白的方式展现出来。先来看一下实际的效果。

2、图层掩膜流程 

        对于图层掩膜的流程,使用流程图描述如下:

         第一步是在地图上加载原始的遥感影像,可以是WMS或者XYZ瓦片。第二步是输入要叠加的升级行政区划范围,这里一般是采用GeoJSON的方式进行获取。第三步是从GeoJSON中解析出空间面信息,构建出遮罩范围,通过绘制遮罩面,设置遮罩面的透明度。同时将无需遮罩的范围留空,这样就能实现空间掩膜的效果。

二、使用插件

        在实现这个需求时,可以完全不用外部的插件,通过Leaflet自己构建Polygon面来实现遮罩掩膜的效果即可。但是使用自己绘制的面时,进行地图缩放时,会有一些不顺畅的原因。因此在开源社区找了一款开源的组件。通过组件来实现地图遮罩,方便又美观。

1、leaflet-mask介绍

        leaflet-mask是一个简单的地图遮罩层控件,继承自L.polygon。我们很多时候希望只显示某块区域内的内容,隐藏或者模糊区域外内容。此插件可以实现传入polygon的latlngs创建对应的遮罩图层。其gitee地址是leaflet-mask。大家可以将代码下载到本地,然后运行其官方的实例即可。

2、核心代码解释 

        对于这个插件来说,核心代码其实非常少,也是很容易看懂的。在下载的源代码中,可以直接打开来看,在src目录下有leaflet-Mask.js。使用文本编辑器或者javascript脚本编辑器打开这个脚本。

/*** 遮罩*/
L.Mask = L.Polygon.extend({options: {isRect: true,    //是否为矩形遮罩,如果为是,则使用northWest,northEast,sourthEast,sourthWest创建矩形遮罩层外边界,如果为false,则使用传入的坐标数组作为遮罩层外边界northWest: { lat: 180.0, lng: -180.0 },  //遮罩层西北角坐标northEast: { lat: 180.0, lng: 180.0 },  //遮罩层东北角坐标sourthEast: { lat: -180.0, lng: 180.0 }, //遮罩层东南角sourthWest: { lat: -180.0, lng: -180.0 }, //遮罩层西南角maskBoundary: null,    //遮罩层边界坐标showPolygons: []    //显示区域},initialize(options) {L.Util.setOptions(this, options);let latlngs = this.getMaskLatLngs();this._setLatLngs(latlngs);},/*** 画遮蔽层的相关方法*思路: 创建一个矩形作为遮罩层,构造函数传入的坐标作为内环* @see https://blog.csdn.net/mapmonster/article/details/104455516* * @param {*} latlngs */getMaskLatLngs() {let latlngs = [];//是矩形遮罩,则使用northWest,northEast,sourthEast,sourthWest创建矩形遮罩层外边界if (this.options.isRect) {this.options.maskBoundary = [];this.options.maskBoundary.push(this.options.northWest);this.options.maskBoundary.push(this.options.sourthWest);this.options.maskBoundary.push(this.options.sourthEast);this.options.maskBoundary.push(this.options.northEast);this.options.maskBoundary.push(this.options.northWest);}latlngs.push(this.options.maskBoundary);for (let i = 0; i < this.options.showPolygons.length; i++) {latlngs = latlngs.concat(this.options.showPolygons[i].getLatLngs());}return latlngs;}
});/*** 合乎leaflet语法* @param {*} options * @returns */
L.mask = function (latlngs, options) {return new L.Mask(latlngs, options);
};

        所有代码加起来,包括注释仅仅有52行,而且采用符合Leaflet的语法方式进行展示。可以看到这里的遮罩层是一个扩展自Polygon类的子类。这里设置了其默认的范围,即四个边界点。

三、完整实例实现

        本节重点将对实例进行完整的介绍,首先我们将遥感影像完整的展示出来。同时在界面右边展示行政区划信息,支持按省级行政区划名称进行检索。点击所在省份,将查询后台的接口返回GeoJSON格式的行政区划边界数据,然后调用leaflet-mask的掩膜对象,实现行政区域的遮罩。

1、后台逻辑实现

        这里介绍省级行政区划列表和查询省级行政区划GeoJson边界信息接口。包括控制层代码和数据库访问层代码。核心代码如下:

package com.yelang.project.extend.earthquake.controller;import java.util.List;import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;import com.yelang.framework.web.controller.BaseController;
import com.yelang.framework.web.domain.AjaxResult;
import com.yelang.framework.web.page.TableDataInfo;
import com.yelang.project.extend.earthquake.domain.EarthQuakeProvinceStatVO;
import com.yelang.project.extend.earthquake.domain.EarthquakeInfo;
import com.yelang.project.extend.earthquake.domain.Province;
import com.yelang.project.extend.earthquake.service.IEarthquakeInfoService;
import com.yelang.project.extend.earthquake.service.IProvinceService;@Controller
@RequestMapping("/eq/province")
public class ProvinceController extends BaseController{private String prefix = "earthquake/province";@Autowiredprivate IProvinceService provinceService;@Autowiredprivate IEarthquakeInfoService earthQuakeInfoService;@RequiresPermissions("eq:province:view")@GetMapping()public String map(){return prefix + "/map";}@RequiresPermissions("eq:province:list")@PostMapping("/list")@ResponseBodypublic TableDataInfo list(Province province){startPage();List<Province> list = provinceService.selectList(province);return getDataTable(list);}@RequiresPermissions("eq:province:geom")@GetMapping("/geojson/{id}")@ResponseBodypublic AjaxResult getGeojson(@PathVariable("id") Long id){Province province = provinceService.findGeoJsonById(id, null);return AjaxResult.success().put("data", province.getGeomJson());}}

        根据省份id查询省份行政区划边界GeoJSON的数据库访问层核心代码如下:

package com.yelang.project.extend.earthquake.mapper;import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yelang.project.extend.earthquake.domain.Province;/*** 省级行政区划数据接口* @author wuzuhu**/
public interface ProvinceMapper extends BaseMapper<Province>{static final String FIND_GEOJSON_SQL="<script>"+ "select st_asgeojson(geom) as geomJson from biz_province "+ "where id = #{id} "+ "<if test='null != name'>and name like concat('%', #{name}, '%')</if>"+ "</script>";@Select(FIND_GEOJSON_SQL)Province findGeoJsonById(@Param("id")Long id,@Param("name")String name);}

2、省级行政区划查询实现

        在地图上我们需要首先展示行政区划列表,这里采用sidebar的组件进行展示。同时在列表中支持按照省级行政区划名称进行模糊查询。

function initSidebar(){//初始化sidebar页面var sidebar = L.control.sidebar('sidebar', {position: 'right'}).addTo(mymap);//默认sidebar打开,并展示一个tab页sidebar.open();$("#xz_info").addClass("active");$("#home").addClass("active");//初始化行政区划表格initHnTownTable();
}function initHnTownTable(){var options = {url: prefix + "/list",createUrl: prefix + "/add",updateUrl: prefix + "/edit/{id}",modalName: "乡镇行政区划",columns: [{checkbox: true},{field: 'id',title: '',visible: false},{field: 'name',title: '省份'},{field: 'type',title: '类别'},{title: '操作',align: 'center',formatter: function(value, row, index) {var actions = [];actions.push('<a class="btn btn-success btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="previewTown(\'' + row.id + '\',\''+row.name+'\')"><i class="fa fa-paper-plane"></i>定位</a>');return actions.join('');}}]};$.table.init(options);
}

3、行政区划定位及掩膜实现 

        点击行政区划列表操作栏中的“定位”按钮,可以实现行政区划定位,以及进行区域掩膜。点击定位的时候,会通过后台的查询接口获取当前点击的行政区划的GeoJSON数据信息。关键方法如下:

function previewTown(gid,name){var myStyle = {color:"white",weight:5,"opacity":1};$.ajax({  type:"get",  url:prefix + "/geojson/" + gid,  data:{},  dataType:"json",  cache:false,processData:false,success:function(result){if(result.code == web_status.SUCCESS){var geojson = JSON.parse(result.data);var areaLayer = L.geoJSON(geojson,{style:myStyle}).addTo(mymap);showLayerGroup.clearLayers();showLayerGroup.addLayer(areaLayer);mymap.setView(areaLayer.getBounds().getCenter(),8);showMask(geojson);}},error:function(){$.modal.alertWarning("获取空间信息失败");}});
}

        通过获取GeoJson的接口获取行政区划的空间位置之后,再调用leaflet-mask的构造方法将遮罩面渲染出来。首先来看一下获取的行政区划GeoJSON数据信息:

function showMask(geojson){var showPolygons = [];var pArray = [];for (var i = 0; i < geojson.coordinates.length; i++) {var points = [];$.each(geojson.coordinates[i],function(k,v){points.push({lat:v[1],lng:v[0]});});//将闭合区域加到遮蔽层上,每次添加完后要再加一次西北角作为下次添加的起点和最后一次的终点pArray = pArray.concat(points);pArray.push(pArray[0]);}var polygon = L.polygon(pArray, { color: 'green' });showPolygons.push(polygon);var mask = L.mask({showPolygons: showPolygons,color: '#C0C0C0',fillOpacity: 1,renderer: L.canvas({ padding: 1 })  //解决遮罩层拖拽与缩放显示不全的Bug});showLayerGroup.addLayer(mask);}

        通过以上的代码即可完成按照行政区划进行掩膜可视化的效果。

4、成果展示

        最后我们来看一下最终生成的省级行政区划掩膜可视化效果。通过点击分析按钮,进行当前省份信息的掩膜可视化。闲言少叙,上图为证。

天津市掩膜效果图 

湖北省掩膜效果图

云南省掩膜效果图 

 贵州省掩膜效果图 

总结

        以上就是本文的主要内容,本文讲解的是一种图层级的掩膜,即使用行政区划图层来进行掩膜。使用场景为,用户只需要在地图页面中展示目标行政区划内的影像信息,对于行政边界外的影像,则不展示。这就是WebGIS中掩膜的一种表达方式。行文仓促,难免有误,欢迎各位专家朋友批评指正,不甚感谢。

本文写作过程中参考以下博客,站在巨人的肩膀上,才能看得更高。

1、Leaflet实现地图按照行政区划遮罩。

2、Leaflet添加掩膜。

3、leaflet实现地图遮罩。

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

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

相关文章

【STM32+HAL】I2C+DMA读取AS5600编码器

一、DMA的应用 有关更多DMA的应用&#xff0c;详见【STM32HAL】DMA应用 二、HAL库配置 1、开启I2C 开启对应DMA及中断 2、开启串口通信 至此&#xff0c;HAL库配置完毕 三、DMA版&#xff08;高效但不稳定&#xff09; 1、as5600.c #include "AS5600.h" #includ…

数据结构与算法 顺序表的基本运算

一、实验内容 编写一个程序实现&#xff0c;实现顺序表的各种基本运算&#xff08;假设顺序表的元素类型为char&#xff09;&#xff0c;并以此为基础设计一个程序完成下列功能&#xff1a; &#xff08;1&#xff09;初始化顺序表&#xff1b; &#xff08;2&#xff09;采…

用指针处理链表(二)

4建立动态链表 所谓建立动态链表是指在程序执行过程中从无到有地建立起一个链表&#xff0c;即一个一个地开辟结点和输入各结点数据,并建立起前后相链的关系。 例11.8 写一函数建立一个有3名学生数据的单向动态链表。 先考虑实现此要求的算法(见图11.12)。 设3个指针变量:he…

企业级快速开发框架 nbsaas-boot 1.1.8-2024 发布了

<parent><groupId>com.nbsaas.boot</groupId><artifactId>nbsaas-boot</artifactId><version>1.1.8-2024</version> </parent> 本次更新内容 1. 重构代码生成器&#xff0c;采用类提取和字段提取两种方式&#xff0c;提取功能…

HDFSRPC通信框架详解

本文主要对HDFSRPC通信框架解析。包括listener&#xff0c;reader&#xff0c;handler&#xff0c;responser等实现类的源码分析。注意hadoop版本为3.1.1。 写在前面 rpc肯定依赖于socket通信&#xff0c;并且使用的是java NIO。读者最好对nio有一定的了解&#xff0c;文章中…

古河云科技校园数字孪生解决方案

智慧校园需将环境信息、资源信息和应用信息全部转化为数字化信息&#xff0c;为管理决策和服务提供强有力的支持。智慧系统集智能化感知、智能化控制、智能化管理、智能化互动反馈、智能化数据分析、智能化视窗等功能于一体&#xff0c;旨在实现校园信息服务的全面提升。 行业…

《机器学习:引领数字化时代的技术革命》

随着科技的不断发展&#xff0c;机器学习作为人工智能的重要支柱之一&#xff0c;正迅速崛起并引领着数字化时代的技术革命。本文将从机器学习的技术进展、技术原理、行业应用案例、面临的挑战与机遇以及未来趋势预测和学习路线等方面展开探讨&#xff0c;为您揭示机器学习的神…

人工智能时代如何高效完成营销内容计划

智能对话升级&#xff01;【Kompas AI】AI对话助手&#xff0c;让沟通更高效 在人工智能时代&#xff0c;要高效完成营销计划&#xff0c;我们可以利用人工智能的多种能力来增强营销策略的精准度和执行效率。借助人工智能的力量&#xff0c;企业不仅可以提高营销计划的执行效率…

DMA知识

提示&#xff1a;文章 文章目录 前言一、背景二、 2.1 2.2 总结 前言 前期疑问&#xff1a; 本文目标&#xff1a; 一、背景 2024年3月26日23:32:43 今天看了DMA存储器到存储器的DMA传输和存储器到外设的DMA实验&#xff0c;在keil仿真可以看到效果。还没有在protues和开发…

使用Flask实现:基于midjourney-proxy的MJ绘画实现(开源)

文章目录 实现效果实现步骤完整源码 实现效果 运行mj.py&#xff0c;如下所示。输入中文&#xff0c;自动生成提示词&#xff0c;自动开始下载。用户选择是否需要变换图片&#xff0c;选择需要对哪个图片变换&#xff0c;自动保存。 之前想做一个网页版&#xff0c;只实现了…

新书速览|Django 5企业级Web应用开发实战:视频教学版

掌握Django框架开发技能&#xff0c;实战投票应用系统和内容管理系统 本书内容 《Django 5企业级Web应用开发实战&#xff1a;视频教学版》精选当前简单、实用和流行的Django实例代码&#xff0c;帮助读者学习和掌握Django 5框架及其相关技术栈的开发知识。本书系统全面、内容…

mysql如何存Emoji表情

如何存Emoji表情 背景解决方案一&#xff1a; 如果是自己搭建的数据库&#xff0c;参考如下。 1&#xff1a;先创建数据库&#xff0c;utf8编码2&#xff1a; 修改mysql 的配置文件 /etc/my.cnf 文件3&#xff1a;然后把你的表和字段也要支持utf8md4编码4&#xff1a;修改你连…

javaWeb教务查询系统

一、简介 在教育管理领域&#xff0c;教务管理系统是一个至关重要的工具&#xff0c;它能够有效地协调学校、教师和学生之间的各种活动。我设计了一个基于JavaWeb的教务管理系统&#xff0c;该系统包括三个角色&#xff1a;管理员、教师和学生。管理员拥有课程管理、学生管理、…

JWT(JSON Web Token)

JSON Web Token 是一种开放标准&#xff0c;用于在网络上安全传输信息的简洁、自包含的方式。它通常被用于身份验证和授权机制。 JWT 由三部分组成&#xff1a;头部&#xff08;Header&#xff09;、载荷&#xff08;Payload&#xff09;和签名&#xff08;Signature&#xff…

微软开源项目Garnet:Redis的竞争者还是替代者?

对于开源社区&#xff0c;最近的一大新闻就是Redis宣布从7.4版本开始&#xff0c;将采用Redis源代码可用许可证&#xff08;RSALv2&#xff09;和服务器端公共许可证&#xff08;SSPLv1&#xff09;的双重许可证&#xff0c;取代原有的BSD三条款许可证。这一变化引发了开发者社…

排序(冒泡/快速/归并)

冒泡排序 时间复杂度为 O(n^2) 原理 比较相邻的元素. 如果第一个比第二个大,就交换他们两个.依次比较每一对相邻的元素—>结果 : 最后的元素是这组数中最大的重复上述步骤 , 除了最后一个[]因为最后一个已经是排好序的了(这组数中最大的那个)]持续对越来越少的元素进行如上…

系列学习前端之第 7 章:一文掌握 AJAX

1、AJAX 简介 AJAX 全称为 Asynchronous JavaScript And XML&#xff08;中文名&#xff1a;阿贾克斯&#xff09;&#xff0c;就是异步的 JS 和 XML。AJAX 不是新的编程语言&#xff0c;而是一种将现有的标准组合在一起使用的新方式。AJAX 可以在浏览器中向服务器发送异步请求…

docker拉取镜像

docker 拉取镜像 命令格式 docker pull 仓库名称[:标签] 从下载过程可以看出&#xff1a; &#xff08;1&#xff09;镜像文件是由若干层组成&#xff0c;即&#xff1a;AUFS联合文件系统。这是实现增量保存与更新的基础 &#xff08;2&#xff09;下载过程会输出各层镜像的信…

面试题-Elasticsearch集群架构和调优手段(超全面)

对于Elasticsearch&#xff08;ES&#xff09;&#xff0c;我了解并有经验。在我之前的公司&#xff0c;我们有一个相对大型的ES集群&#xff0c;以下是该集群的架构和一些调优手段的概述&#xff1a; 1. 集群架构 集群规模&#xff1a;我们的ES集群由15个节点组成&#xff0c…

水果店如何开发自己的微信小程序_新鲜生活,触手可及

水果店微信小程序&#xff1a;新鲜生活&#xff0c;触手可及 在这个快节奏的时代&#xff0c;我们都在追求更高效、更便捷的生活方式。而微信小程序&#xff0c;正是这样一个让生活变得更加轻松便捷的神奇工具。今天&#xff0c;我要向大家介绍的&#xff0c;就是一家独具匠心…