Weather
数据来源
weather来源于openweather网站 需要密钥 aki-key
示例数据
下面给出三组数据进行展示
json数据详情如下
json
{
"coord": {
"lon": 108.9286,
"lat": 34.2583
},
"weather": [
{
"id": 804,
"main": "Clouds",
"description": "overcast clouds",
"icon": "04d"
}
],
"base": "stations",
"main": {
"temp": 7.45,
"feels_like": 7.45,
"temp_min": 7.45,
"temp_max": 7.45,
"pressure": 1028,
"humidity": 100,
"sea_level": 1028,
"grnd_level": 977
},
"visibility": 27,
"wind": {
"speed": 0.16,
"deg": 111,
"gust": 0.25
},
"clouds": {
"all": 100
},
"dt": 1682232424,
"sys": {
"type": 1,
"id": 9645,
"country": "CN",
"sunrise": 1682201049,
"sunset": 1682248857
},
"timezone": 28800,
"id": 1790630,
"name": "Xi'an",
"cod": 200
}
天气类型说明
800 ---- 晴天 200 ~ 232 ---- 雷电天气 600 ~ 622 ---- 下雪天气 701 ~ 781 ---- 雾霾天气 801 ~ 804 ---- 多云天气 500 ~ 531 ---- 雨天 300 ~ 321 ---- 雨天
布局
js
<!DOCTYPE html>
<html lang="zh-cn" dir="ltr">
<head>
<meta charset="utf-8">
<title>Weather App made in xiao tian~</title>
<link rel="stylesheet" href="style.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Linking BoxIcon for Icon -->
<link href='https://unpkg.com/boxicons@2.0.9/css/boxicons.min.css' rel='stylesheet'>
</head>
<body>
<div class="wrapper">
<header><i class='bx bx-left-arrow-alt'></i>Weather App</header>
<section class="input-part">
<p class="info-txt"></p>
<div class="content">
<input type="text" spellcheck="false" placeholder="Enter city name" required>
<div class="separator"></div>
<button>Get Device Location</button>
</div>
</section>
<section class="weather-part">
<img src="#" alt="Weather Icon">
<div class="temp">
<span class="numb">_</span>
<span class="deg">°</span>C
</div>
<div class="weather">_ _</div>
<div class="location">
<i class='bx bx-map'></i>
<span>_, _</span>
</div>
<div class="bottom-details">
<div class="column feels">
<i class='bx bxs-thermometer'></i>
<div class="details">
<div class="temp">
<span class="numb-2">_</span>
<span class="deg">°</span>C
</div>
<p>Feels like</p>
</div>
</div>
<div class="column humidity">
<i class='bx bxs-droplet-half'></i>
<div class="details">
<span>_</span>
<p>Humidity</p>
</div>
</div>
</div>
</section>
</div>
<script src="weather.js"></script>
</body>
</html>
js 功能实现
js
// 获取DOM节点
const wrapper = document.querySelector(".wrapper"),
inputPart = document.querySelector(".input-part"),
infoTxt = inputPart.querySelector(".info-txt"),
inputField = inputPart.querySelector("input"),
locationBtn = inputPart.querySelector("button"),
weatherPart = wrapper.querySelector(".weather-part"),
wIcon = weatherPart.querySelector("img"),
arrowBack = wrapper.querySelector("header i");
let api;
/**
* input 添加Keyup 如果key === enter && != '' 时,发起请求 requestApi
*/
inputField.addEventListener("keyup", e => {
if (e.key == "Enter" && inputField.value != "") {
requestApi(inputField.value);
}
});
/**
* @param geolocation - 获取
* 点击获取当前location时, button -添加click事件,
* 如果 浏览器有geolocation时, 则进行获取当前位置getCurrentPosition方法
* - 成功 获取数据,进行响应 显示
* - 失败 进行报错显示
* 如果浏览器没有该属性时,则alert提醒 浏览器不支持该功能
*/
locationBtn.addEventListener("click", () => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(onSuccess, onError);
} else {
alert("Your browser not support geolocation api");
}
});
/**
* @param requestApi() 请求api方法
* @param city 请求的城市
* @param fetchData() 发起请求
*/
function requestApi(city) {
api = `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&appid=a017e6cba7dc219a9338d233e37a9ae3`;
fetchData();
}
/**
* @param onSuccess() 成功的方法
* @param latitude 维度
* @param longitude 经度
*
* 成功回调的函数, 将经纬度给api 然后发起请求数据
*/
function onSuccess(position) {
const { latitude, longitude } = position.coords;
api = `https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&units=metric&appid=a017e6cba7dc219a9338d233e37a9ae3`;
fetchData();
}
/**
* @param onError() 失败的方法
* 失败了 则进行对应的错误报错
*/
function onError(error) {
infoTxt.innerText = error.message;
infoTxt.classList.add("error");
}
/**
* @param fetchData() 请求数据的方法
* @param api openweather---apikey
*
* 请求数据的过程中,进行文字提示
* 使用fetch() 传入api地址,该方法会返回一个Promise
* 使用then进行响应处理
* 第一个then 将响应体解析为JSON格式 然后调用weatherDetail()处理解析后的数据
* 若出错则catch 将文字替换为错误提醒 并将pending更新为error
*/
function fetchData() {
infoTxt.innerText = "Getting weather details...";
infoTxt.classList.add("pending");
fetch(api).then(res => res.json()).then(result => weatherDetails(result)).catch(() => {
infoTxt.innerText = "Something went wrong";
infoTxt.classList.replace("pending", "error");
});
}
/**
* @param info Txt of weather details
* @param info.code 不同天气类型对应的code状态码
* @param wIcon 天气图标
*/
function weatherDetails(info) {
// once we received data from api then we'll hide pendging message and show weather
if (info.cod == "404") {
infoTxt.classList.replace("pending", "error");
infoTxt.innerText = `${inputField.value} isn't a valid city name`;
} else {
const city = info.name;
const country = info.sys.country;
const { description, id } = info.weather[0];
console.log(info);
const { temp, feels_like, humidity } = info.main;
// using custom icon according to the id which api return us
if (id == 800) {
wIcon.src = "icons/clear.svg";
} else if (id >= 200 && id <= 232) {
wIcon.src = "icons/storm.svg";
} else if (id >= 600 && id <= 622) {
wIcon.src = "icons/snow.svg";
} else if (id >= 701 && id <= 781) {
wIcon.src = "icons/haze.svg";
} else if (id >= 801 && id <= 804) {
wIcon.src = "icons/cloud.svg";
} else if ((id >= 500 && id <= 531) || (id >= 300 && id <= 321)) {
wIcon.src = "icons/rain.svg";
}
// 进行天气详情数据的替换
weatherPart.querySelector(".temp .numb").innerText = Math.floor(temp);
weatherPart.querySelector(".weather").innerText = description;
weatherPart.querySelector(".location span").innerText = `${city}, ${country}`;
weatherPart.querySelector(".temp .numb-2").innerText = Math.floor(feels_like);
weatherPart.querySelector(".humidity span").innerText = `${humidity}%`;
infoTxt.classList.remove("pending", "error");
infoTxt.innerText = "";
inputField.value = "";
wrapper.classList.add("active");
}
}
/**
* @param arrowBack 返回上一页
* 触发click 移除active状态 返回首页
*/
arrowBack.addEventListener("click", () => {
wrapper.classList.remove("active");
});