基于 Leaflet 的 WebGIS 省域区县天气可视化实现
基于 Leaflet 和 WebGIS 技术实现省域区县天气可视化。通过百度天气接口获取数据存入 PostgreSQL,利用 SpringBoot 提供后端查询服务。前端使用 Leaflet 加载 GeoJSON 数据,结合自定义色带映射气温颜色,并引入碰撞检测组件优化标签展示。实现了湖南省和西藏自治区的天气实况地图展示,涵盖低温与高温区县统计,为气象预报及灾害预警提供直观的数据支持。

基于 Leaflet 和 WebGIS 技术实现省域区县天气可视化。通过百度天气接口获取数据存入 PostgreSQL,利用 SpringBoot 提供后端查询服务。前端使用 Leaflet 加载 GeoJSON 数据,结合自定义色带映射气温颜色,并引入碰撞检测组件优化标签展示。实现了湖南省和西藏自治区的天气实况地图展示,涵盖低温与高温区县统计,为气象预报及灾害预警提供直观的数据支持。

地理信息系统(GIS)技术与 Web 技术的深度融合,为地理信息的可视化展示带来了机遇。WebGIS 能够将地理空间数据以直观、便捷的方式呈现给用户。天气数据作为与人们生活息息相关的重要地理信息之一,其可视化展示对于气象预报、灾害预警等领域有着重要意义。本文将从 WebGIS 视角出发,探讨如何利用 Leaflet 这一开源 JavaScript 库,实现省域区县天气的可视化。
本节介绍相关的空间数据基础,包括省级空间范围、区县行政空间范围以及区县驻地等信息。为了在 WebGIS 展示时将天气数据直接与行政区划关联,我们在天气表中预留了行政区划编码的字段。
省域信息主要用于省级行政范围的展示,以及通过百度天气接口获取具体天气信息时,首先需要通过省级行政区划代码或者下级区县信息,然后循环调用官方接口来获取天气信息。
查询省份信息 SQL:
select * from biz_province;
返回结果中的 code 即为该省份对应的行政区划代码,如 130000 表示河北省。查询下级区县信息 SQL(以河北省为例):
select * from biz_area t where t.province_code = '130000';
通过上述 SQL 查询可获取指定省份的下属区县信息,后续即可根据该区县 code 获取天气信息。
涉及的数据表如下:
| 序号 | 表名 | 说明 |
|---|---|---|
| 1 | biz_weather_now | 实时天气信息表 |
| 2 | biz_area | 区县信息表 |
| 3 | biz_geographic_name | 城市信息表 |
区县天气信息检索 SQL(以查询湖南省 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'
AND T.province_code = '430000'
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;
天气变化的复杂性和不确定性,使得准确、及时地获取和展示天气信息成为一项极具挑战性的任务。这里的天气信息数据源以百度天气为例,通过查询获取区域内的天气信息。
核心 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();
//将天气信息持久化到数据库中
if(null != bdResult) {
Long weatherId = IdWorker.getId();
bdResult.getWeatherNow().setPkId(weatherId);
bdResult.getWeatherNow().setLocationCode(areaCode);
weatherService.insertWeatherInfo(bdResult);
}
Thread.sleep(1500 + random.nextInt(1000));
}
}
}
由于区县信息和城市信息的采集和整理的时候可能存在不一致的情况。比如在行政区划调整的过程,有的县级名称可能会改成区。为了保证在查询能关联查到,需要将两张表的数据进行清理统一,修改成统一的名称即可。
本文采用 SpringBoot 框架为 WebGIS 提供后台服务,主要涉及的功能有天气数据查询的实现。
使用 Java 进行区县天气数据查询,基于 MybatisPlus 定义数据视图对象:
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);
}
业务逻辑层的实际这里比较简单不做详细叙述。
控制层作为接收前端的请求并且返回响应数据的重要组件,这里主要提供展示界面的跳转以及区县天气数据列表的获取:
package com.yelang.project.meteorology.controller;
import java.util.List;
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;
@GetMapping("/province")
public String province(){
return prefix + "/province";
}
@GetMapping("/list/{pcode}")
@ResponseBody
public AjaxResult ewsnProvinceList(@PathVariable("pcode") String pcode){
String day = "2025-08-17";
List<AreaWeatherVO> dataList = weatherNowService.getWeatherByProvinceAndday(pcode,day);
AjaxResult.success().put(, dataList);
}
}
在众多可用于 WebGIS 开发的工具和库中,Leaflet 凭借其轻量级、易上手、功能强大且高度可定制的特点脱颖而出。
为了直观的展示天气的气温信息,对气温的值、颜色、气温描述等信息进行定义。气温颜色色带(colormap)是一种常用的工具,用于将数值范围映射到颜色范围。
| 气温范围 (℃) | 颜色描述 | 十六进制颜色代码 |
|---|---|---|
| 45℃以上 | 深红色 | #8B0000 |
| 40℃ - 45℃ | 红色 | #FF0000 |
| 35℃ - 40℃ | 橙红色 | #FF4500 |
| 30℃ - 35℃ | 橙色 | #FFA500 |
| 25℃ - 30℃ | 黄色 | #FFFF00 |
| 20℃ - 25℃ | 浅绿色 | #90EE90 |
| 15℃ - 20℃ | 绿色 | #00FF00 |
| 10℃ - 15℃ | 青色 | #00FFFF |
| 5℃ - 10℃ | 浅蓝色 | #ADD8E6 |
| 0℃ - 5℃ | 蓝色 | #0000FF |
| -5℃ - 0℃ | 深蓝色 | #4169E1 |
| -10℃ - -5℃ | 紫色 | #800080 |
| -15℃ - -10℃ | 深紫色 | #4B0082 |
| -20℃ - -15℃ | 黑色 | #000000 |
在 JavaScript 中定义以上信息:
//气温及颜色配置
var weatherColorList = [
{name:"-20℃ - -15℃",color:"#000000",rgb:new Color(0,0,0),colorDesc:"黑色"},
{name:"-15℃ - -10℃",color:"#4B0082",rgb:new Color(75,0,130),colorDesc:"深紫色"},
{name:"-10℃ - -5℃",color:"#800080",rgb:new Color(128,0,128),colorDesc:"紫色"},
{name:"-5℃ - 0℃",color:"#4169E1",rgb:new Color(65,105,225),colorDesc:"深蓝色"},
{name:"0℃ - 5℃",color:"#0000FF",rgb:new Color(0,0,),:},
{:,:,: (,,),:},
{:,:,: (,,),:},
{:,:,: (,,),:},
{:,:,: (,,),:},
{:,:,: (,,),:},
{:,:,: (,,),:},
{:,:,: (,,),:},
{:,:,: (,,),:},
{:,:,: (,,),:}
];
在 WebGIS 中使用色带即 colorMap 的方式对气温颜色进行定义,同时在地图中展示相应的图例:
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);
});
为了方便对气温数据进行展示,同时考虑到区县数量是比较多的,因此在标绘展示时不要让中文标签被遮挡住,这里我们采用碰撞检测组件来进行辅助提升可视化效果:
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.(.(areaData.),{: {:color,:color,:,:, : }}).(mymap);
myIcon = L.({ : , : , :[,], :[,], : (i,color,areaData) });
showLayerGroup.(areaLayer);
L.([areaData., areaData.], { : myIcon}).(collisionLayer);
collisionLayer.(showLayerGroup);
}
}
},
:(){
$.modal.();
}
});
}
本节将主要描述 WebGIS 的区县天气展示,从湖南省和西藏自治区两个地区来进行展示。

从整体来看,湖南 8 月 17 日 8 点左右的全省气温信息比之前的要好多了(整体范围从 20 度到 29 度,均小于 23 度),温差变大,体感舒适度有所提高了。低温前五区县:
湖南省 郴州市 桂东县 20.00
湖南省 衡阳市 南岳区 21.00
湖南省 郴州市 汝城县 21.00
湖南省 湘西土家族苗族自治州 花垣县 21.00
湖南省 株洲市 炎陵县 22.00
气温从高到低前 5 区县是:
湖南省 岳阳市 岳阳楼区 29.00
湖南省 岳阳市 云溪区 29.00
湖南省 益阳市 资阳区 29.00
湖南省 益阳市 赫山区 29.00
湖南省 岳阳市 君山区 29.00

从整体来看,西藏自治区 8 月 17 日 8 点左右的全省气温信还是比较低,这跟其高海拔有关系(整体范围从 2 度到 21 度,跨度还是非常大的)。低温前五区县:
西藏自治区 那曲市 嘉黎县 2.00
西藏自治区 山南市 错那县 4.00
西藏自治区 日喀则市 亚东县 4.00
西藏自治区 山南市 措美县 4.00
西藏自治区 昌都市 芒康县 5.00
气温从高到低前 5 区县是:
西藏自治区 林芝市 墨脱县 21.00
西藏自治区 林芝市 朗县 14.00
西藏自治区 林芝市 察隅县 14.00
西藏自治区 林芝市 波密县 14.00
西藏自治区 山南市 曲松县 14.00
可以看到,在西藏的林芝市,其气温跟湖南是差不多的,而且林芝市温度最高的是墨脱县。不得不说,林芝市的气温是真不错,不愧是西藏江南。
本文旨在为读者提供一份系统、实用的省域区县天气可视化实战攻略,帮助读者掌握基于 Leaflet 和 WebGIS 技术实现天气可视化的完整流程和关键技巧。通过本文的阅读,无论你是 GIS 领域的专业人士,还是对 Web 开发和地理信息可视化感兴趣的初学者,都将能够对基于 Leaflet 的省域区县天气可视化有一个全面而深入的了解,并掌握实现这一目标的具体方法和技巧。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online