唤醒80年代记忆:基于百度地图的一次老式天气预报的WebGIS构建之旅

目录

一、省会城市信息构建

1、省会城市空间查询

2、Java后台查询

二、Java省会城市天气查询

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

2、响应对象属性介绍

3、省会天气实况展示

三、WebGIS应用构建

1、背景音乐集成

2、城市标记及天气展示

3、城市轮播

4、成果展示

四、总结


前言

在数字技术飞速发展的今天,我们常常沉浸于各种高科技带来的便捷与震撼之中,却容易忽视那些曾经陪伴我们成长、承载着时代记忆的旧事物。80年代的天气预报,便是这样一份珍贵的文化遗产。它以简洁而质朴的方式,传递着天气信息,也传递着那个时代的气息。那种对自然的敬畏、对信息的渴望,以及一家人共同分享的温馨氛围,都深深烙印在我们的记忆中。然而,随着时间的推移,天气预报的形式已经发生了翻天覆地的变化。高清的画面、精准的数据、个性化的推送......这些现代技术带来的便利固然令人欣喜,但也在一定程度上让我们失去了那份对天气预报本身的纯粹情感。于是,一个想法在心中萌生:能不能用现代的技术手段,重现80年代的天气预报,让那些旧时光的记忆重新回到我们的生活中?WebGIS技术的出现,为我们提供了这样一个绝佳的机会。它能够将地理信息与网络技术相结合,实现地图的可视化展示和数据的动态交互。而百度天气作为国内领先的天气数据服务平台,提供了丰富而准确的天气信息。将两者相结合,我们或许能够构建出一个既具有80年代风格,又融合了现代技术优势的天气预报系统。

我们的目标是构建一个能够唤醒80年代记忆的老式天气预报系统。这个播报系统需要播放我们熟悉的天气预报背景音乐。在播报形式上,播报内容将涵盖基本的天气信息,如温度、时间和明日天气等。尽管界面和播报形式是80年代的风格,但数据来源却是现代的。我们将整合百度天气提供的实时数据,确保天气信息的准确性和及时性。通过WebGIS技术,我们可以在地图上直观地展示不同地区的天气情况,用户可以通过简单的操作查看全国各地的天气预报。

在构建这样一个系统的过程中,我们面临着诸多技术挑战。为此,我们将采用现代的前端开发技术,如HTML5、CSS3和JavaScript,结合WebGIS框架,实现一个既复古又现代的界面。其次,80年代的语音播报风格与现代的语音合成技术存在较大差异。此外,我们还需要编写一套符合当时风格的播报脚本,确保播报内容的准确性和趣味性。最后,整合百度天气数据并将其与WebGIS地图相结合,需要解决数据格式转换、地图渲染优化等问题。我们将利用WebGIS平台提供的数据接口和地图渲染工具,实现数据的无缝对接和高效展示。

这不仅仅是一个技术项目,更是一次情感的探索和文化的传承。通过构建这样一个80年代风格的天气预报系统,我们希望能够唤起更多人对那个时代的美好回忆,同时也展示现代技术在文化传承方面的巨大潜力。在未来的工作中,我们还将继续优化系统功能,增加更多互动元素,如用户自定义播报内容、分享功能等,让这个系统不仅仅是一个展示平台,更是一个能够与用户产生情感共鸣的互动空间。这是一次穿越时空的构建之旅,也是一次对过去的致敬和对未来的探索。让我们一起踏上这段旅程,用现代的技术手段,唤醒那些沉睡在记忆深处的80年代天气预报,让旧时光在新技术的助力下重新焕发生机。

一、省会城市信息构建

在进行省会城市天气预报的WebGIS可视化开发之前,首先我们需要对全国的省会城市信息进行查询。在后面调用百度天气接口时也需要使用省会城市名称。因此这里首先介绍如何查询省会城市空间信息以及如何在Java中进行后台的城市信息查询。

1、省会城市空间查询

在之前的博文中,我们介绍了城市点位信息和省份信息,在进行省会城市信息查询时,也同样需要使用这几张表。查询语句如下:

sql 复制代码
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

在Navicat客户端中执行以上语句后,可以在客户端看到以下查询结果:

在后面的操作中,我们就需要使用这个返回结果中的省会城市的中心点经纬度的位置来进行天气的查询,最后返回给前台进行使用。

2、Java后台查询

在SQL中实现上述的查询之后,接下来我们就可以将相关的查询逻辑封装成Java接口,来供前端调用。在Java中的Mapper类来实现以上的查询服务,Mapper.java的核心代码如下:

java 复制代码
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();

当然,为了方便方法的复用,这里我们将Mapper的查询能力封装成一个通用的方法,在Service中进行实现,通过提供对外方法,供第三方服务进行调用。Service的调用比较简单,代码如下:

java 复制代码
@Override
public List<ProvinceAbbreviationsVo> findProvinceAbbreviations() {
	return this.baseMapper.findProvinceAbbreviations();
}

最后实现一个Controller来将Service的服务接口对外提供出来。这里不进行赘述,如果需要交流讨论,可以在评论区或者私信留言均可。

二、Java省会城市天气查询

有了这个查询省会天气的服务之后,接下来我们就可以根据不同省会城市的经纬度,利用百度天气接口的国内经纬度查询能力,直接返回对应城市的天气以及未来的天气预报。本节就来深入介绍一下如何使用经纬度来进行查询天气,并且对相应对象的属性进行一个简单的介绍。

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

为了实现根据省会城市的经纬度来查询所在城市的天气信息,首先我们需要定义百度天气接口的方法,定义方法如下:

java 复制代码
/**
* - 根据经纬度和坐标类型查询指定地点的天气信息 
* @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);

有了这个接口之后,接下来我们就可以从前面获取的省会城市列表中来进行循环调用,传入省会城市的经纬度位置就可以实现天气情况的查询。调用实例代码如下:

java 复制代码
/**
* 获取省会城市天气预报信息
* @throws InterruptedException 
*/
@Test
public void testGetProvinceWeather() throws InterruptedException {
	Random random = new Random();
	List<LinkedHashMap<String, Object>> provinceWeatherData = new ArrayList<LinkedHashMap<String,Object>>(34);
	List<ProvinceAbbreviationsVo> provinceList = geographicNameService.findProvinceAbbreviations();
	Gson gson = new Gson();
	for (ProvinceAbbreviationsVo vo : provinceList) {
		//经纬度,经度在前纬度在后,逗号分隔。
		String location	= vo.getCityLon() + "," + vo.getCityLat();
		//lat:39.066114,lon:117.213135,w_name:"晴",city:"天津",temp:"3-14",color:"#03a9f4",two:"11/22 3-12"
		HttpResponse<String> result = baiduWeatherApiService.getByLocation(location, DATA_TYPE, "wgs84");
		if(StringUtils.isNotEmpty(result.getBodyResult())) {
			LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>();
			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));
	}
	String weatherStr = gson.toJson(provinceWeatherData);
	System.out.println(provinceWeatherData);
	System.out.println(weatherStr);
}

需要说明的是,这里采用线程休眠的原因是为了避免造成并发调用。当然,如果您的账号权限比较高,不受并发的限制就无所谓了。

2、响应对象属性介绍

为了方便标注,实现省会城市的实时天气信息展示以及未来一天的天气情况展示,需要定义一个标准的响应对象,通过上述代码可以看出我们使用一个hashmap来进行实现。示例如下:

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

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

3、省会天气实况展示

这里以12月7日为例,使用上述程序查询出来12月7日到12月8日两天的省会城市天气预报数据如下:

bash 复制代码
[{"lat":"39.903162481","lon":"116.401006456","city":"北京市","w_name":"晴","temp":"-2-10","two":"12-8 -4-5"},
{"lat":"39.083383854","lon":"117.193764008","city":"天津市","w_name":"晴","temp":"-2-11","two":"12-8 -2-5"},
{"lat":"38.041795673","lon":"114.509022491","city":"石家庄市","w_name":"晴","temp":"0-15","two":"12-8 -2-7"},
{"lat":"37.8699777370001","lon":"112.543459413","city":"太原市","w_name":"晴","temp":"-8-9","two":"12-8 -7-6"},
{"lat":"40.84174369","lon":"111.742890453","city":"呼和浩特市","w_name":"多云","temp":"-14--1","two":"12-8 -10-0"},{"lat":"41.8043596680001","lon":"123.425789521","city":"沈阳市","w_name":"晴","temp":"-8-5","two":"12-8 -7-1"},
{"lat":"43.8149938920001","lon":"125.31766745","city":"长春市","w_name":"晴","temp":"-12-0","two":"12-8 -11--4"},
{"lat":"45.8019539320001","lon":"126.528652017","city":"哈尔滨市","w_name":"多云","temp":"-18--5","two":"12-8 -21--8"},{"lat":"31.2318491390001","lon":"121.46965015","city":"上海市","w_name":"霾","temp":"10-20","two":"12-8 7-16"},
{"lat":"32.06249645","lon":"118.792223921","city":"南京市","w_name":"晴","temp":"6-19","two":"12-8 4-15"},
{"lat":"30.276062563","lon":"120.150302306","city":"杭州市","w_name":"晴","temp":"9-19","two":"12-8 7-17"},
{"lat":"31.823360144","lon":"117.222184326","city":"合肥市","w_name":"晴","temp":"3-18","two":"12-8 1-14"},
{"lat":"26.0772329970001","lon":"119.291018877","city":"福州市","w_name":"多云","temp":"14-24","two":"12-8 14-23"},{"lat":"28.6855336350001","lon":"115.853297824","city":"南昌市","w_name":"多云","temp":"11-20","two":"12-8 10-19"},{"lat":"36.6655797230001","lon":"116.988607998","city":"济南市","w_name":"晴","temp":"-1-15","two":"12-8 5-10"},
{"lat":"34.7474463120001","lon":"113.620086008","city":"郑州市","w_name":"晴","temp":"1-18","two":"12-8 0-11"},
{"lat":"30.5951977820001","lon":"114.299439726","city":"武汉市","w_name":"雾","temp":"3-18","two":"12-8 3-17"},
{"lat":"28.230799873","lon":"112.934511917","city":"长沙市","w_name":"霾","temp":"8-18","two":"12-8 7-17"},
{"lat":"23.1306783370001","lon":"113.259864444","city":"广州市","w_name":"多云","temp":"14-25","two":"12-8 13-25"},{"lat":"22.819317503","lon":"108.362490315","city":"南宁市","w_name":"多云","temp":"15-23","two":"12-8 14-24"},
{"lat":"20.050034829","lon":"110.196179915","city":"海口市","w_name":"晴","temp":"18-25","two":"12-8 19-25"},
{"lat":"29.566484528","lon":"106.546994525","city":"重庆市","w_name":"晴","temp":"9-15","two":"12-8 11-17"},
{"lat":"30.574891279","lon":"104.064316153","city":"成都市","w_name":"晴","temp":"6-18","two":"12-8 8-13"},
{"lat":"26.6496315200001","lon":"106.626281501","city":"贵阳市","w_name":"多云","temp":"4-12","two":"12-8 7-15"},
{"lat":"24.88255573","lon":"102.830594244","city":"昆明市","w_name":"多云","temp":"4-16","two":"12-8 6-17"},
{"lat":"29.6558675410001","lon":"91.1700828420001","city":"拉萨市","w_name":"晴","temp":"-5-13","two":"12-8 -4-12"},{"lat":"34.3431558230001","lon":"108.935725754","city":"西安市","w_name":"晴","temp":"2-14","two":"12-8 2-13"},
{"lat":"36.0614637570001","lon":"103.831432958","city":"兰州市","w_name":"晴","temp":"-6-7","two":"12-8 -5-8"},
{"lat":"36.6168144980001","lon":"101.775387587","city":"西宁市","w_name":"晴","temp":"-10-6","two":"12-8 -7-6"},{"lat":"38.4870919210001","lon":"106.226758099","city":"银川市","w_name":"多云","temp":"-3-6","two":"12-8 -5-8"},{"lat":"43.8255140370001","lon":"87.6149638000001","city":"乌鲁木齐市","w_name":"大雾","temp":"-6-1","two":"12-8 -7--1"},{"lat":"25.036365684","lon":"121.563739724","city":"台北市","w_name":"多云","temp":"17-23","two":"12-8 18-21"}]

三、WebGIS应用构建

本节将重点介绍如何在WebGIS中进行应用的构建,在使用百度天气创建好相应的省会城市列表的天气信息后,接下来要做的就是要集成经典的天气预报北京音乐,同时使用Leaflet来标注所有的省会城市位置,并且要展示天气信息,最后要根据位置来实现城市的轮播展示。

1、背景音乐集成

背景音乐这里我们找了一个很经典的,是我们小时候百听不厌的背景音乐。当然,大家也可以根据自己的喜好来调整。在html中增加一个在线视频,然后需要我们隐藏画面,只保留音乐,核心代码如下:

html 复制代码
<!-- 视频标签,设置为循环播放,但初始时不自动播放 -->
<video id="backgroundVideo" loop muted>
   <source src="./weather/music.mp4" type="video/mp4">
   您的浏览器不支持HTML5视频。
</video>

为了隐藏画面,这里我们使用CSS样式的方式进行控制,代码如下:

javascript 复制代码
/* 隐藏视频画面 */
video {
   display: none;
}

为了演示的效果,我们将设置网页进行延迟播放,设置方法如下:

javascript 复制代码
// 获取视频元素和按钮
var video = document.getElementById('backgroundVideo');
// 设置音量为20%
video.volume = 0.2;
var button = document.getElementById('playButton');	
// 页面加载后延迟2秒自动播放
window.onload = function() {
	initWeather();
	setTimeout(function() {
		video.play(); // 开始播放
		video.muted = false; // 取消静音
		preview();//城市天气进行轮播	
	}, 5000); // 2000毫秒(2秒)后执行
};

2、城市标记及天气展示

城市标记及天气展示比较简单,使用Leaflet来进行位置的标注即可,这里给出示例代码:

javascript 复制代码
function initWeather(){
	var collisionLayer = L.LayerGroup.collision({margin:3});
	for(var i=0;i<dataJson.length;i++){
		var html;
		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);
}

天气的信息标注代码如下,通过以上代码就可以实现今日天气和明日天气的网页展示:

javascript 复制代码
function buildHtml(dataJson,index){
	var html = "";
	html += "<div class='marsBlackPanel' style='background:"+getRandomColor()+";' animation-spaceInDown><div class='marsBlackPanel-text' ><b>"+dataJson.city + "&nbsp;" + dataJson.w_name + "&nbsp;"+ dataJson.temp +"℃</b><span></span></div>";
	html += "<div class='marsBlackPanel-text' style=''>" + ""+ dataJson.two+ " ℃</div>";
	html += "</div>";
	return html;
}

最后还有一个随机颜色的生成,使用随机颜色是为了保证生成的页面的颜色能够更加区别明显。

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

3、城市轮播

为了实现每个省会城市都可以进行轮播,这里我们根据位置将地图的视图中心点进行重绘。最终的效果看起来就是一个会跳动的地图。这里我们使用定时器的方式来进行切换不同城市。核心代码如下:

javascript 复制代码
function preview(){
	// 设置定时器,每隔2秒执行一次
	const intervalId = setInterval(() => {
	// 如果索引超出了数组范围,清除定时器并停止执行
    if (currentIndex >= dataJson.length) {
		currentIndex = 0;
	}
	// 获取当前索引对应的元素
	const currentElement = dataJson[currentIndex];
	//如果不为空,先移除marker
    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);
	// 索引加1,准备获取下一个元素
	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、成果展示

经过以上的步骤,基本就可以实现带音乐播放的天气小应用。页面效果如下:

如果您也感兴趣,跟随博文一起来动手实践吧。这里录了一个最终的视频效果,如果感兴趣可以看看:https://live.csdn.net/v/504506

四、总结

以上就是本文的主要内容,本文构建了一个能够唤醒80年代记忆的老式天气预报系统。这不仅仅是一个技术项目,更是一次情感的探索和文化的传承。通过构建这样一个80年代风格的天气预报系统,我们希望能够唤起更多人对那个时代的美好回忆,同时也展示现代技术在文化传承方面的巨大潜力。在未来的工作中,我们还将继续优化系统功能,增加更多互动元素,如用户自定义播报内容、分享功能等,让这个系统不仅仅是一个展示平台,更是一个能够与用户产生情感共鸣的互动空间。这是一次穿越时空的构建之旅,也是一次对过去的致敬和对未来的探索。让我们一起踏上这段旅程,用现代的技术手段,唤醒那些沉睡在记忆深处的80年代天气预报,让旧时光在新技术的助力下重新焕发生机。