跳到主要内容基于 Leaflet 的 WebGIS 省域区县天气可视化实现 | 极客日志Java大前端java
基于 Leaflet 的 WebGIS 省域区县天气可视化实现
一、空间数据基础 本节介绍相关的空间数据基础,本内容需要使用到省级空间范围、区县行政空间范围以及区县驻地等信息进行检索。同时为了在 WebGIS 展示时将天气数据直接与行政区划关联,我们在天气表中预留了行政区划编码的字段。 1、省域空间检索 省域信息有两个使用场景:一是省级行政范围的展示,二是通过百度天气接口获取具体天气信息时,首先需要通过省级行政区划代码或者下级区县信息,然后循环调用官方接口来获…
MqEngine51K 浏览 一、空间数据基础
本节介绍相关的空间数据基础,本内容需要使用到省级空间范围、区县行政空间范围以及区县驻地等信息进行检索。同时为了在 WebGIS 展示时将天气数据直接与行政区划关联,我们在天气表中预留了行政区划编码的字段。
1、省域空间检索
省域信息有两个使用场景:一是省级行政范围的展示,二是通过百度天气接口获取具体天气信息时,首先需要通过省级行政区划代码或者下级区县信息,然后循环调用官方接口来获取天气信息。省域信息及表结构如下:
select * from biz_province;

上图中返回的 code 就是该省份对应的行政区划代码,如:130000 表示河北省。有了这个代码之后如何查询下级的区县信息呢,这里就需要使用到区县信息表,查询语句如下(以河北省为例):
select * from biz_area t where t.province_code = '130000';

通过以上的 SQL 查询就可以获取到指定省份的下属区县信息,后续就可以根据该区县 code 获取天气信息。
2、区县天气信息检索
为了实现区县的天气信息,需要涉及的数据表如下表所示:
| 序号 | 表名 | 说明 |
| 1 | biz_weather_now | 实时天气信息表 |
| 2 | biz_area | 区县信息表 |
| 3 | biz_geographic_name | 城市信息表 |
直接给出区县天气信息检索的 SQL(以查询 2025 年 8 月 17 日的湖南省 430000 的区县天气信息为例):
SELECT t2.*, T.province_code, T.province_name, T.area_code, T.area_name, t1.geom, st_asgeojson ( T.geom ) geomJson, st_x ( t1.geom ) lon, st_y ( t1.geom ) lat FROM biz_weather_now t2, biz_area T, biz_geographic_name t1 WHERE to_char( t2.uptime, 'YYYY-MM-DD' ) = '2025-08-17' T.province_code T.area_name t1.NAME T.area_code t2.location_code st_contains(t.geom, t1.geom) t.area_code;
微信扫一扫,关注极客日志
微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具
- Keycode 信息
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
- Escape 与 Native 编解码
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
- JavaScript / HTML 格式化
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
- JavaScript 压缩与混淆
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
AND
=
'430000'
AND
=
AND
=
AND
ORDER
BY
二、天气数据简介
天气变化的复杂性和不确定性,使得准确、及时地获取和展示天气信息成为一项极具挑战性的任务。天气数据是整个研究内容的核心,这里的天气信息数据源我们以百度天气为例,通过查询获取区域内的天气信息,为天气等气象服务提供数据支持。本节将介绍如何获取省域天气以及可能遇到的区县名称不一致的情况如何解决。
1、省域天气数据获取
在之前的内容中,我们对如何通过行政区划代码获取对应的天气信息进行了详细的介绍。在这篇内容中,我们仅介绍单个区县的天气信息检索,在本文的研究内容中,我们需要采集不同的区县信息,因此我们需要提前采集省域区县的天气信息。首先我们来看一下如何在后台查询区县和获取对应的天气信息,核心的 Java 代码如下:
@Test public void bdWeather2PGWithProvince() throws InterruptedException { String provinceCode = "430000"; Random random = new Random(); QueryWrapper<Area> queryWrapper = new QueryWrapper<Area>(); queryWrapper.like("province_code", provinceCode); List<Area> areaList = areaService.list(queryWrapper); if(StringUtils.isNotEmpty(areaList)) { for (Area area : areaList) { String areaCode = area.getAreaCode(); HttpResponse<String> result = baiduWeatherApiService.getWeather(areaCode, DATA_TYPE); Gson gson = new Gson(); BdWeatherDTO bdWeatherInfo = gson.fromJson(result.getBodyResult(), BdWeatherDTO.class); WeatherInfoDTO bdResult = bdWeatherInfo.getResult();
运行以上代码即可实现省域区县天气的入库处理,来看一下 PG 数据库中的实际天气信息:
通过省域区县的天气信息采集就有了天气数据分析展示的基础。接下来就可以进行具体应用的设计与实现工作。
2、区县名称不一致
由于区县信息和城市信息的采集和整理的时候可能存在不一致的情况。比如在行政区划调整的过程,有的县级名称可能会改成区,以长沙市为例,望城县就改成了望城区。在区县信息表中名称为望城区,而在城市信息表中可能还叫望城县,为了保证在查询能关联查到,因此需要将两张表的数据进行清理统一,修改方法可以参考相关的官方名称,修改成统一的名称即可。
三、SpringBoot 后台实现
本文采用 SpringBoot 框架为 WebGIS 提供后台服务,主要涉及的功能有天气数据查询的实现,关于区县的天气信息查询检索在第一节中有所介绍,这里将重点从后台实现的角度进行描述。主要从以下两个方面来进行,第一个是后台的天气的数据查询实现,第二个是 Java 的控制层的具体实现。
1、Java 后台天气数据查询
使用 Java 进行区县天气数据查询比较简单,首先基于 MybatisPlus 需要定义数据视图对象,关键的 Java 代码如下所示:
package com.yelang.project.meteorology.mapper; import java.util.List; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.yelang.project.meteorology.domain.AreaWeatherVO; import com.yelang.project.meteorology.domain.WeatherNow; public interface WeatherNowMapper extends BaseMapper<WeatherNow>{ final static String GET_WEATHER_BYPROVINCE_ANDDAY = "<script>" + " SELECT t2.*,T.province_code,T.province_name,T.city_code,T.city_name,T.area_code,T.area_name, " + " t1.geom,st_asgeojson ( T.geom ) geomJson,st_x ( t1.geom ) lon,st_y ( t1.geom ) lat " + " FROM biz_weather_now t2,biz_area T,biz_geographic_name t1 " + " WHERE to_char( t2.uptime, 'YYYY-MM-DD' ) = #{day} AND T.province_code = #{provinceCode} " + " AND T.area_name = t1.NAME AND T.area_code = t2.location_code AND st_contains(t.geom, t1.geom) " + " ORDER BY t.area_code " + "</script>"; @Select(GET_WEATHER_BYPROVINCE_ANDDAY) List<AreaWeatherVO> getWeatherByProvinceAndday(@Param("provinceCode") String provinceCode,@Param("day") String day); }
查询结果对应的视图对象代码如下,为了最大程度的实现对象的复用,视图对象集成了实时天气对象 JavaBean:
package com.yelang.project.meteorology.domain; import java.io.Serializable; import com.baomidou.mybatisplus.annotation.TableField; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; @Data @ToString(callSuper=true)
2、控制层实现
控制层作为接收前端的请求并且返回响应数据的重要组件,这里主要提供展示界面的跳转以及区县天气数据列表的获取,核心代码如下:
package com.yelang.project.meteorology.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.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; 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.project.meteorology.domain.AreaWeatherVO; import com.yelang.project.meteorology.service.IWeatherNowService; @Controller @RequestMapping("/met/province/weather") public class ProvinceWeatherController extends BaseController{ private String prefix = "meteorology/weather"; @Autowired private IWeatherNowService weatherNowService; @RequiresPermissions("met:province:weather:map") @GetMapping("/province") public String province(){ return prefix + "/province"; } @RequiresPermissions("met:province:weather:list") @GetMapping("/list/{pcode}") @ResponseBody public AjaxResult ewsnProvinceList(@PathVariable("pcode") String pcode){ String day = "2025-08-17"; List<AreaWeatherVO> dataList = weatherNowService.getWeatherByProvinceAndday(pcode,day); return AjaxResult.success().put("data", dataList); } }
以上就是使用 SpringBoot 的后台实现,接下来基于后台的相关 API 来实现 WebGIS 的展示。
四、WebGIS 前端实现
在众多可用于 WebGIS 开发的工具和库中,Leaflet 凭借其轻量级、易上手、功能强大且高度可定制的特点脱颖而出,成为众多开发者在地理信息可视化项目中的首选工具之一。本节将重点介绍如何使用 Leaflet 来进行 WebGIS 开发和实现。在面向天气的应用中,主要进行气温颜色和数据的展示两个部分,接下来将详细叙述。
1、气温颜色及图例初始化
为了直观的展示天气的气温信息,我们首先对气温的值、颜色、气温描述等信息进行定义,这是后续的可视化展示的基础。气温颜色色带(colormap)是一种常用的工具,用于将数值范围映射到颜色范围。以下是一个详细的气温颜色色带表格,包括颜色的十六进制代码和对应的气温范围。这个色带可以用于气象数据可视化、地理信息系统(GIS)或其他需要表示温度变化的场景。
| 气温范围 (℃) | 颜色描述 | 十六进制颜色代码 | RGB 颜色表示 (R, G, B) |
|---|
| 45℃以上 | 深红色 | #8B0000 | (139, 0, 0) |
| 40℃ - 45℃ | 红色 | #FF0000 | (255, 0, 0) |
| 35℃ - 40℃ | 橙红色 | #FF4500 | (255, 69, 0) |
| 30℃ - 35℃ | 橙色 | #FFA500 | (255, 165, 0) |
| 25℃ - 30℃ | 黄色 | #FFFF00 | (255, 255, 0) |
| 20℃ - 25℃ | 浅绿色 | #90EE90 | (144, 238, 144) |
| 15℃ - 20℃ | 绿色 | #00FF00 | (0, 255, 0) |
| 10℃ - 15℃ | 青色 | #00FFFF | (0, 255, 255) |
| 5℃ - 10℃ | 浅蓝色 | #ADD8E6 | (173, 216, 230) |
| 0℃ - 5℃ | 蓝色 | #0000FF | (0, 0, 255) |
| -5℃ - 0℃ | 深蓝色 | #4169E1 | (65, 105, 225) |
| -10℃ - -5℃ | 紫色 | #800080 | (128, 0, 128) |
| -15℃ - -10℃ | 深紫色 | #4B0082 | (75, 0, 130) |
| -20℃ - -15℃ | 黑色 | #000000 | (0, 0, 0) |
在 WebGIS 中需要使用色带即 colorMap 的方式对气温颜色进行定义,同时在地图中展示相应的图例(需要注意的是,这里的气温极值取 -20 和 45 度,这两个值在实际生活中可能有所调整,大家自己灵活处理),定义的关键代码如下:
var DIY_BLUE_GREEN_YELLOW_RED_SCHEME; $(document).ready(function () { initSidebar(); var legendData = new Array(); var colorArray = new Array(); for(var i =0;i<weatherColorList.length;i++){ var _tempData = weatherColorList[i]; legendData.push({ label: "\xa0\xa0"+_tempData.name , type: "rectangle", radius: 12, color: _tempData.color, fillColor: _tempData.color, fillOpacity: 0.8, weight: 2}); } colorArray.push(_tempData.rgb); DIY_BLUE_GREEN_YELLOW_RED_SCHEME = new MultiColorScheme('', -20,45 ,colorArray); initLegend(legendData); });
2、气温数据展示实现
为了方便对气温数据进行展示,同时考虑到区县数量是比较多的,因此在标绘展示时不要让中文标签被遮挡住,因此这里我们采用碰撞检测组件来进行辅助提升可视化效果,碰撞组件定义如下:
var collisionLayer = L.LayerGroup.collision({margin:2});
定义好碰撞组件后,接下来可以实现对气温数据展示,关键代码如下:
function previewWeather(pid,provinceCode,name){ previewProvince(pid,name); $.ajax({ type:"get", url:ctx + "/met/province/weather/list/" + provinceCode, data:{}, dataType:"json", cache:false, processData:false, success:function(result){ if(result.code == web_status.SUCCESS){ $("#title_info").html(name+"天气实况<sub>更新时间:20250817" +"</sub>"); collisionLayer.clearLayers(); var dataArray = result.data; if(dataArray != null && dataArray.length > 1){ var legendData = new Array(); for(var i =0;i< dataArray.length;i++){ var areaData = dataArray[i]; var color = makeColor(areaData.temp,-20,45,DIY_BLUE_GREEN_YELLOW_RED_SCHEME); var areaLayer = L.geoJSON(JSON.parse(areaData.geomJson),{style: {color:color,fillColor:color,weight:3,"opacity":0.65, fillOpacity: 0.65 }}).addTo(mymap); var myIcon = L.divIcon({ iconSize: null, className: '', popupAnchor:[5,5], shadowAnchor:[5,5], html: buildShowInfo(i,color,areaData) }); showLayerGroup.addLayer(areaLayer);
以上就完成了气温数据的 WebGIS 前端展示实现代码。下面我们来看一下实际的成果。
五、成果展示
本节将主要描述 WebGIS 的区县天气展示,这里我们从湖南省和西藏自治区两个地区来进行展示。湖南省应该是一个比较典型的气温高的省份,而西藏则是气温比较低的省份。同时可以对比以下实际的色温展示成果。
1、湖南省天气展示
从整体来看,湖南 8 月 17 日 8 点左右的全省气温信息比之前的要好多了(整体范围从 20 度到 29 度,均小于 23 度),温差变大,体感舒适度有所提高了。接下来我们从低温前五和高温前五来看下,首先看下低温前 5 是哪些区县:
湖南省 郴州市 桂东县 20.00 湖南省 衡阳市 南岳区 21.00 湖南省 郴州市 汝城县 21.00 湖南省 湘西土家族苗族自治州 花垣县 21.00 湖南省 株洲市 炎陵县 22.00
湖南省 岳阳市 岳阳楼区 29.00 湖南省 岳阳市 云溪区 29.00 湖南省 益阳市 资阳区 29.00 湖南省 益阳市 赫山区 29.00 湖南省 岳阳市 君山区 29.00
2、西藏自治区天气展示
从整体来看,西藏自治区 8 月 17 日 8 点左右的全省气温信还是比较低,这跟其高海拔有关系(整体范围从 2 度到 21 度,跨度还是非常大的)。接下来我们从低温前五和高温前五来看下,首先看下低温前 5 是哪些区县:
西藏自治区 那曲市 嘉黎县 2.00 西藏自治区 山南市 错那县 4.00 西藏自治区 日喀则市 亚东县 4.00 西藏自治区 山南市 措美县 4.00 西藏自治区 昌都市 芒康县 5.00
西藏自治区 林芝市 墨脱县 21.00 西藏自治区 林芝市 朗县 14.00 西藏自治区 林芝市 察隅县 14.00 西藏自治区 林芝市 波密县 14.00 西藏自治区 山南市 曲松县 14.00
可以看到,在西藏的林芝市,其气温跟湖南是差不多的,而且林芝市温度最高的是墨脱县,又一次聚焦到了墨脱县。不得不说,林芝市的气温是真不错,不愧是西藏江南。