跳到主要内容基于 Leaflet 与 WebGIS 的省域区县天气可视化实现 | 极客日志Java大前端java
基于 Leaflet 与 WebGIS 的省域区县天气可视化实现
综述由AI生成通过 Leaflet 和 WebGIS 技术实现省域及区县天气数据的可视化展示。利用 SpringBoot 后端结合 PostgreSQL 空间数据库存储行政区划与实时天气信息,前端使用 Leaflet 库加载 GeoJSON 数据并渲染地图图层。通过自定义气温色带方案将温度数值映射为颜色,并结合碰撞检测组件优化大量区县级标签的显示效果。最终实现了湖南省与西藏自治区的天气实况地图展示,支持按省份查询、气温热力分布及图例交互,为气象预报与灾害预警提供直观的数据支撑。
极客零度16 浏览 前言
地理信息系统(GIS)技术与 Web 技术的深度融合,为地理信息的可视化展示带来了新的机遇。WebGIS 能够将地理空间数据以直观、便捷的方式呈现给用户。天气数据作为重要的地理信息之一,其可视化展示对于气象预报、灾害预警等领域具有重要意义。本文将从 WebGIS 视角出发,探讨如何利用 Leaflet 开源 JavaScript 库,实现省域区县天气的可视化。
一、空间数据基础
本节介绍相关的空间数据基础,涉及省级空间范围、区县行政空间范围以及区县驻地等信息检索。为了在 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(以查询湖南省 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 st_contains(t.geom, t1.geom) t.area_code;
=
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();
if(null != bdResult) {
Long weatherId = IdWorker.getId();
bdResult.getWeatherNow().setPkId(weatherId);
bdResult.getWeatherNow().setLocationCode(areaCode);
weatherService.insertWeatherInfo(bdResult);
}
Thread.sleep(1500 + random.nextInt(1000));
}
}
}
2、区县名称不一致
由于区县信息和城市信息的采集和整理可能存在不一致的情况。例如在行政区划调整过程中,有的县级名称可能会改成区。为了保证查询能关联查到,需要将两张表的数据进行清理统一,修改成统一的名称即可。
三、SpringBoot 后台实现
本文采用 SpringBoot 框架为 WebGIS 提供后台服务,主要涉及的功能有天气数据查询的实现。重点从后台实现的角度进行描述,包括后台的天气数据查询实现和 Java 控制层的具体实现。
1、Java 后台天气数据查询
使用 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.domain;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Data
@ToString(callSuper=true)
@EqualsAndHashCode(callSuper=false)
public class AreaWeatherVO extends WeatherNow implements Serializable{
private static final long serialVersionUID = -7559774548761847068L;
@TableField(exist = false,value= "province_code")
private String provinceCode;
@TableField(exist = false,value= "province_name")
private String provinceName;
@TableField(exist = false,value= "city_code")
private String cityCode;
@TableField(exist = false,value= "city_name")
private String cityName;
@TableField(exist = false,value= "area_name")
private String areaName;
@TableField(exist = false)
private String geomJson;
private String lat;
private String lon;
}
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);
}
}
四、WebGIS 前端实现
Leaflet 凭借其轻量级、易上手、功能强大且高度可定制的特点,成为地理信息可视化项目中的首选工具之一。本节重点介绍如何使用 Leaflet 进行 WebGIS 开发和实现。
1、气温颜色及图例初始化
为了直观展示天气的气温信息,首先对气温的值、颜色、气温描述等信息进行定义。以下是一个详细的气温颜色色带表格:
| 气温范围 (℃) | 颜色描述 | 十六进制颜色代码 | 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) |
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,255),colorDesc:"蓝色"},
{name:"5℃ - 10℃",color:"#ADD8E6",rgb:new Color(173,216,230),colorDesc:"浅蓝色"},
{name:"10℃ - 15℃",color:"#00FFFF",rgb:new Color(0,255,255),colorDesc:"青色"},
{name:"15℃ - 20℃",color:"#00FF00",rgb:new Color(0,255,0),colorDesc:"绿色"},
{name:"20℃ - 25℃",color:"#90EE90",rgb:new Color(144,238,144),colorDesc:"浅绿色"},
{name:"25℃ - 30℃",color:"#FFFF00",rgb:new Color(255,255,0),colorDesc:"黄色"},
{name:"30℃ - 35℃",color:"#FFA500",rgb:new Color(255,165,0),colorDesc:"橙色"},
{name:"35℃ - 40℃",color:"#FF4500",rgb:new Color(255,69,0),colorDesc:"橙红色"},
{name:"40℃ - 45℃",color:"#FF0000",rgb:new Color(255,0,0),colorDesc:"红色"},
{name:"45℃以上",color:"#8B0000",rgb: new Color(139,0,0),colorDesc:"深红色"}
];
在 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);
});
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);
L.marker([areaData.lat, areaData.lon], { icon: myIcon}).addTo(collisionLayer);
collisionLayer.addTo(showLayerGroup);
}
}
}
},
error:function(){
$.modal.alertWarning("获取空间信息失败");
}
});
}
五、成果展示
本节描述 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
可以看到,在西藏的林芝市,其气温跟湖南是差不多的,而且林芝市温度最高的是墨脱县。林芝市的气温确实不错,被称为西藏江南。
六、总结
本文介绍了基于 Leaflet 和 WebGIS 技术实现天气可视化的完整流程和关键技巧。通过本文的阅读,读者能够对基于 Leaflet 的省域区县天气可视化有一个全面而深入的了解,并掌握实现这一目标的具体方法和技巧。
相关免费在线工具
- 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