跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Java大前端java

基于百度天气 API 与 Leaflet 的 WebGIS 天气预报系统实现

利用 Java 后端结合百度天气 API 获取全国省会城市实时数据,并通过 Leaflet 框架在前端实现 WebGIS 可视化展示。内容涵盖数据库空间查询、API 接口集成、前端地图标记及轮播动画的实现细节。项目旨在通过现代技术重现复古风格的天气预报界面,展示了前后端协作处理地理信息与动态交互的完整流程。

刀狂发布于 2026/4/7更新于 2026/7/2050 浏览
基于百度天气 API 与 Leaflet 的 WebGIS 天气预报系统实现

前言

现代技术让我们有机会用新的方式重现旧时的记忆。本项目利用百度天气 API 获取实时数据,结合 WebGIS 技术构建一个具有 80 年代风格的天气预报系统。界面和播报形式保留复古元素,但数据来源保持现代准确性。

文章配图

在开发过程中,我们面临几个主要挑战:如何整合地图可视化、如何处理高并发下的 API 调用限制以及如何还原经典的播报风格。通过 HTML5、CSS3、JavaScript 以及 Java 后端,我们实现了数据的无缝对接和高效展示。

一、省会城市信息构建

在进行可视化之前,首先需要查询全国省会城市的空间信息,以便后续调用天气接口。这里涉及数据库中的点位信息和省份信息表。

1、省会城市空间查询

使用 SQL 语句配合 PostGIS 函数进行查询,核心逻辑是筛选出标记为'省会城市'、'直辖市'或'首都'的记录,并关联省份表获取经纬度及 GeoJSON 数据。

SELECT T.NAME cityName, T.pinYin, T.bz, T.slx, tc.code provinceCode, tc.NAME provinceName, st_x(T.geom) cityLon, st_y(T.geom) cityLat, dict.dict_label provinceAbbreviations, st_asgeojson(tc.geom) geomJson 
FROM biz_geographic_name T, biz_province tc, sys_dict_data dict 
WHERE T.bz IN ('省会城市', '直辖市', '首都') 
AND st_contains(tc.geom, T.geom) 
AND dict.dict_value = tc.code 
ORDER BY tc.code

执行后得到的结果包含城市名称、拼音、经纬度及省份代码,这些字段将作为后续天气查询的基础参数。

2、Java 后台查询

将上述 SQL 逻辑封装到 MyBatis Mapper 中,方便前端调用。Mapper 类核心代码如下:

static final String FIND_PROVINCEABBREVIATIONS_LIST = "<script>" + " SELECT T.name cityName,T.pinYin,T.bz,T.slx,tc.code provinceCode,tc.NAME provinceName, " + " st_x(T.geom) cityLon,st_y(T.geom) cityLat,dict.dict_label provinceAbbreviations, " + " st_asgeojson(tc.geom) geomJson " + " FROM biz_geographic_name T,biz_province tc,sys_dict_data dict " + " WHERE T.bz IN('省会城市', '直辖市', '首都') AND st_contains(tc.geom, T.geom) AND dict.dict_value = tc.code " + " order by tc.code " + "</script>";

@Select(FIND_PROVINCEABBREVIATIONS_LIST)
List<ProvinceAbbreviationsVo> findProvinceAbbreviations();

为了复用性,我们在 Service 层进一步封装了查询方法,并通过 Controller 暴露 RESTful 接口供第三方服务调用。

二、Java 省会城市天气查询

有了城市列表后,接下来根据经纬度调用百度天气接口获取实时预报。本节介绍接口集成及响应对象的处理。

1、与百度开放平台集成天气

定义 HTTP 接口方法,支持传入经纬度和坐标类型。注意经度在前、纬度在后,逗号分隔。

/**
 * - 根据经纬度和坐标类型查询指定地点的天气信息
 * @param location 经纬度,经度在前纬度在后,逗号分隔。支持类型:bd09mc/bd09ll/wgs84/gcj02
 * @param data_type 请求数据类型。数据类型有:now/fc/index/alert/fc_hour/all,控制返回内容,默认值无
 * @param coordtype 支持类型:wgs84/bd09ll/bd09mc/gcj02 默认值:wgs84
 * @return
 */
@GetHttpInterface("/")
public HttpResponse<String> getByLocation(@QueryPar("location") String location, @QueryPar("data_type") String data_type, @QueryPar("coordtype") String coordtype);

调用实例中,我们遍历城市列表,逐个请求天气数据。为了避免触发接口的并发限制,在循环中加入了随机休眠时间。

@Test
public void testGetProvinceWeather() throws InterruptedException {
    Random random = new Random();
    List<LinkedHashMap<String, Object>> provinceWeatherData = new ArrayList<>();
    List<ProvinceAbbreviationsVo> provinceList = geographicNameService.findProvinceAbbreviations();
    Gson gson = new Gson();
    
    for (ProvinceAbbreviationsVo vo : provinceList) {
        String location = vo.getCityLon() + "," + vo.getCityLat();
        HttpResponse<String> result = baiduWeatherApiService.getByLocation(location, DATA_TYPE, "wgs84");
        
        if (StringUtils.isNotEmpty(result.getBodyResult())) {
            LinkedHashMap<String, Object> map = new LinkedHashMap<>();
            map.put("lat", vo.getCityLat());
            map.put("lon", vo.getCityLon());
            map.put("city", vo.getCityName());
            
            BdWeatherDTO bdWeatherInfo = gson.fromJson(result.getBodyResult(), BdWeatherDTO.class);
            WeatherInfoDTO weatherInfoDTO = bdWeatherInfo.getResult();
            map.put("w_name", weatherInfoDTO.getWeatherNow().getText());
            
            List<WeatherForecasts> forecasts = weatherInfoDTO.getForecasts();
            if (StringUtils.isNotEmpty(forecasts)) {
                WeatherForecasts today = forecasts.get(0);
                map.put("temp", today.getLow() + "-" + today.getHigh());
                WeatherForecasts tomorrow = forecasts.get(1);
                Date tempDate = tomorrow.getDate();
                String two = (tempDate.getMonth() + 1) + "-" + tempDate.getDate() + " " + tomorrow.getLow() + "-" + tomorrow.getHigh();
                map.put("two", two);
            }
            provinceWeatherData.add(map);
        }
        Thread.sleep(1500 + random.nextInt(1000));
    }
    System.out.println(gson.toJson(provinceWeatherData));
}

2、响应对象属性介绍

为了方便前端渲染,我们将返回数据标准化为一个 JSON 对象结构,包含经纬度、城市名、当前天气、今日气温及明日预报。

序号参数名称说明
1lat纬度
2lon经度
3city城市名称
4w_name天气说明
5temp气温
6two明日天气

示例数据如下:

{
  "lat":"39.903162481",
  "lon":"116.401006456",
  "city":"北京市",
  "w_name":"晴",
  "temp":"-2-10",
  "two":"12-8 -4-5"
}

3、省会天气实况展示

程序运行后可生成包含全国省会城市两天预报的完整数据集,例如北京、上海、广州等地的实时状态均可通过此接口获取。

三、WebGIS 应用构建

数据准备就绪后,重点转向前端的可视化呈现。我们使用 Leaflet 框架加载地图,集成经典背景音乐,并实现城市轮播效果。

1、背景音乐集成

为了还原 80 年代氛围,我们引入了经典的天气预报背景音乐。在 HTML 中使用 <video> 标签播放音频,并通过 CSS 隐藏视频画面,仅保留声音。

<!-- 视频标签,设置为循环播放,初始时不自动播放 -->
<video loop muted>
  <source src="./weather/music.mp4" type="video/mp4">
  您的浏览器不支持 HTML5 视频。
</video>
/* 隐藏视频画面 */
video { display: none; }

页面加载后延迟 2 秒自动播放音乐,并将音量调整为 20% 以避免突兀。

var video = document.getElementById('backgroundVideo');
video.volume = 0.2;
window.onload = function() {
    initWeather();
    setTimeout(function() {
        video.play();
        video.muted = false;
        preview(); // 开始城市轮播
    }, 2000);
};

2、城市标记及天气展示

使用 Leaflet 在地图上标注所有省会城市位置,并在 Marker 上显示天气卡片。为了区分不同城市,我们为每个标记分配了随机颜色。

function initWeather(){
    var collisionLayer = L.LayerGroup.collision({margin:3});
    for(var i=0; i<dataJson.length; i++){
        var marker = L.marker([dataJson[i].lat, dataJson[i].lon], {
            icon: L.divIcon({
                iconSize: null,
                className: '',
                popupAnchor:[5,5],
                shadowAnchor:[5,5],
                html: buildHtml(dataJson[i],i)
            })
        }).addTo(collisionLayer);
    }
    collisionLayer.addTo(map);
}

天气信息的 HTML 构建逻辑如下,注意修复了原代码中的语法错误:

function buildHtml(dataJson, index){
    var html = '';
    html += '<div style="color:' + getRandomColor() + '; animation: spaceInDown;">';
    html += '<div><b>' + dataJson.city + '&nbsp;' + dataJson.w_name + '&nbsp;' + dataJson.temp + '℃</b><span></span></div>';
    html += '<div>' + dataJson.two + ' ℃</div>';
    html += '</div>';
    return html;
}

function getRandomColor() {
    var letters = '0123456789ABCDEF';
    var color = '#';
    for (var i = 0; i < 6; i++) {
        color += letters[Math.floor(Math.random() * 16)];
    }
    return color;
}

3、城市轮播

为了让地图动起来,我们使用定时器每隔 3 秒切换一次中心点,模拟老式电视新闻中地图跳动的效果。

function preview(){
    const intervalId = setInterval(() => {
        if (currentIndex >= dataJson.length) {
            currentIndex = 0;
        }
        const currentElement = dataJson[currentIndex];
        
        if(dymicMarker != null){
            map.removeLayer(dymicMarker);
        }
        dymicMarker = L.marker([currentElement.lat, currentElement.lon]).addTo(map);
        setTargetSelect(dymicMarker);
        console.log(`当前元素:${currentElement}`);
        map.setView([currentElement.lat, currentElement.lon], 8);
        
        currentIndex++;
    }, 3000);
}

function setTargetSelect(e){
    var i = 1;
    var int = setInterval(() => {
        if(!e._map) clearInterval(int);
        if (i < -1) { i = 1; }
        i = i - 0.08;
        if (i < 0) e.setOpacity(i * -1);
        else e.setOpacity(i);
    }, 60);
}

4、成果展示

完成以上步骤后,即可得到一个带有背景音乐、动态地图标记及轮播功能的天气小应用。

文章配图

四、总结

本教程展示了如何利用 Java 后端处理地理数据与天气 API,并结合 Leaflet 实现 WebGIS 可视化。从数据库的空间查询到前端的动画交互,整个流程涵盖了前后端协作的关键环节。通过这个项目,我们不仅实现了功能,也探索了如何用现代技术承载怀旧的情感体验。

目录

  1. 前言
  2. 一、省会城市信息构建
  3. 1、省会城市空间查询
  4. 2、Java 后台查询
  5. 二、Java 省会城市天气查询
  6. 1、与百度开放平台集成天气
  7. 2、响应对象属性介绍
  8. 3、省会天气实况展示
  9. 三、WebGIS 应用构建
  10. 1、背景音乐集成
  11. 2、城市标记及天气展示
  12. 3、城市轮播
  13. 4、成果展示
  14. 四、总结
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Flutter 三方库 bavard 的鸿蒙化适配指南:语义化聊天协议与机器人逻辑
  • Elasticsearch 核心概念与 Java 客户端实战
  • Python SQLAlchemy ORM 数据库操作指南
  • Qwen-Agent 工具调用入门:基于 Qwen2.5-7B-Instruct 的实践
  • 谷歌 TurboQuant 算法:内存占用减少至少 6 倍
  • C++ 二叉搜索树:增删查改与 key/value 场景实现
  • Flask 集成 flask-admin 后台及 flask-login 权限管理
  • VRChat 跨语言交流工具 VRCT 使用指南
  • GitHub Copilot Agent Skills:打造跨项目 AI 专属工具箱
  • ComfyUI 是什么?节点式 AI 绘画工作流详解
  • OpenClaw Web Search 工具配置与渠道详解
  • OpenClaw 本地 AI 智能体:部署与实战指南
  • RAG 与大模型对接的 9 大隐藏挑战及解决方案
  • 数据结构:常见时间与空间复杂度解析
  • Gerrit 配置:Gitweb 集成
  • 数据结构:带头双向循环链表的定义与实现
  • 微/纳米机器人赋能肿瘤精准治疗:GBM 领域近五年进展
  • Node-RED 智能家居自动化配置指南
  • OpenClaw 安装与飞书机器人接入教程
  • WebStorm 安装与首次配置指南

相关免费在线工具

  • 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