之前做过的大屏项目一般是在内网环境中使用,所以一般顶部不牵扯展示城市和天气。但是这次做的是放在外网的,所以简单实现一下展示城市名称和当前实时天气信息。
获取当前所处位置
获取当前定位可以通过浏览器原生的Geolocation API获取经纬度信息。
js
function getLocation() {
return new Promise((resolve, reject) => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
(position) => {
const lat = position.coords.latitude;
const lon = position.coords.longitude;
resolve({lat, lon});
console.log('当前位置:', lat, lon);
},
(error) => {
console.error('无法获取位置:', error.message);
reject(error);
}
);
}
})
}
需要注意,Geolocation API是异步的,所以这里用 Promise 进行了简单的封装。另外这里只能获取到经纬度,无法获取到所在城市名称,需要通过逆地理编码的方式实现。
逆地理编码
目前国内主要是御三家 提供逆地理编码 的服务,但是都需要进行付费,不过唯一可以庆幸的是各家都有免费额度。
如果你的大屏部署在外网,国外的Nominatim 是完全免费的,咱们这边目前是无法访问的。官网地址也放一个nominatim.openstreetmap.org。
这里我以腾讯的逆地理编码服务为例子简单写一下:
js
async function getCityName(lat, lon) {
const sig = CryptoJs.MD5(`/ws/geocoder/v1/?key=${你的key}&location=${lat},${lon}${你的签名}`).toString();
const {result} = await request.get(`/tencent/ws/geocoder/v1/?key=${你的key}&location=${lat},${lon}&sig=${sig}`);
return `${result.address_component.city}-${result.address_component.district}`
}
这里需要代理一下,我这里的代理如下:
js
'/tencent': {
target: 'https://apis.map.qq.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/tencent/, '')
},
获取天气
天气信息目前咱们这边有和风天气,提供了一定的免费额度。
但是我在网上找到一个外面的,但是咱们这边能访问到的Open-Meteo ,官方地址也放一下open-meteo.com。
特点如下:
- 无需注册、无 API Key、无调用限制
- 支持全球经纬度实时天气 + 未来7天预报
- 数据来源:欧洲中期天气预报中心(ECMWF)等权威机构
唯一不好的一点在于返回的都是英文数据,需要认为的转成中文。
js
// 部分天气中英文映射
const WEATHER_CODE_MAP = {
0: { en: 'Clear sky', zh: '晴' },
1: { en: 'Mainly clear', zh: '晴转多云' },
2: { en: 'Partly cloudy', zh: '多云' },
3: { en: 'Overcast', zh: '阴' },
45: { en: 'Fog', zh: '雾' },
48: { en: 'Depositing rime fog', zh: '冻雾' },
51: { en: 'Drizzle: Light', zh: '小雨' },
53: { en: 'Drizzle: Moderate', zh: '中雨' },
55: { en: 'Drizzle: Dense', zh: '大雨' },
61: { en: 'Rain: Slight', zh: '小雨' },
63: { en: 'Rain: Moderate', zh: '中雨' },
65: { en: 'Rain: Heavy', zh: '大雨' },
71: { en: 'Snow fall: Slight', zh: '小雪' },
73: { en: 'Snow fall: Moderate', zh: '中雪' },
75: { en: 'Snow fall: Heavy', zh: '大雪' },
95: { en: 'Thunderstorm', zh: '雷阵雨' },
96: { en: 'Thunderstorm with slight hail', zh: '雷阵雨伴小冰雹' },
99: { en: 'Thunderstorm with heavy hail', zh: '雷阵雨伴大冰雹' }
};
js
// 获取天气
async function getWeather(lat, lon) {
const result = await request.get(`https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t_weather=true`);
const code = result.current_weather.weathercode;
return WEATHER_CODE_MAP[code] || {en: 'Unknown', zh: '未知'};
}
这个是不需要代理的,因为Open-Meteo 本身支持CORS。
总结
获取经纬度和城市信息,以及天气信息在技术上没什么难度。
主要的问题点在于很多东西都是付费的,自己玩玩还好,但要是真的上线正式环境一定要防备被别人恶意刷爆。
之前我还见过一个大屏上实时展示天气状况,卫星地图上前面有一层蒙版展示。如果是下雨的话有雨滴打在屏幕上的感觉,效果非常不错,回头实现完分享给大家。
欢迎关注我的公众号李剑一,分享更多的干货,畅聊圈内八卦。