Skip to content

Instantly share code, notes, and snippets.

@XiaoPanPanKevinPan
Created January 5, 2022 12:02
Show Gist options
  • Save XiaoPanPanKevinPan/ee14a0b25d531cdea33c1ff69a608462 to your computer and use it in GitHub Desktop.
Save XiaoPanPanKevinPan/ee14a0b25d531cdea33c1ff69a608462 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<title>期末報告</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/normalize.css@8.0.1/normalize.css" />
<script>
let cwbToken = ""; // 氣象局 API 之權杖須自行取得
document.addEventListener("DOMContentLoaded", async()=>{
try{
let displayWeather = (temperature, humidity)=>{
let temperatureMeter = document.querySelector("#weatherInfo .temperature.meter .bar");
let humidityMeter = document.querySelector("#weatherInfo .humidity.meter .bar");
temperatureMeter.innerHTML = `${temperature} °C`;
temperatureMeter.style.setProperty("--value", Math.min(Math.max(temperature + 30, 0), 100) / 100);
humidityMeter.innerHTML = `${(humidity*100).toFixed(1)} %`;
humidityMeter.style.setProperty("--value", humidity);
};
let changeWallpaper = async ()=>{
let newWallpaperBlob = URL.createObjectURL(await(await
fetch("https://picsum.photos/1080/1920")).blob());
let main = document.querySelector("main");
main.style["background-image"] = `url("${newWallpaperBlob}")`;
};
let cwbData = await fetch(`https://opendata.cwb.gov.tw/api/v1/rest/datastore/O-A0001-001?Authorization=${cwbToken}&format=JSON`);
let cwbJson = await cwbData.json();
console.log(cwbJson);
if(cwbJson.success != "true"){
throw "錯誤:取得之資料不可用。success != \"true\"";
}
let selector = document.querySelector("#locationNameSelector");
selector.innerHTML = `<option>請選擇監測地點</option>`;
let locations = cwbJson.records.location;
for(let location of locations){
/* get each ${location.parameter}, which in this form
* {
* parameterName: ${name},
* parameterValue: ${value}
* }
* remapped it into this form
* ${name}: ${value}
*/
let newParameters = {};
for(let param of location.parameter){
newParameters[param.parameterName] = param.parameterValue;
}
location.parameter = newParameters;
/* do the same as above, but do for ${weatherElement} */
let newWeatherElements = {};
for(let elem of location.weatherElement){
newWeatherElements[elem.elementName] = elem.elementValue;
}
location.weatherElement = newWeatherElements;
/* and then create the full name */
location["locationFullName"] =
`${location.parameter["CITY"]}${location.parameter["TOWN"]} ${location.locationName}`;
}
locations.sort((location1, location2)=>{
return location1.locationFullName.localeCompare(location2.locationFullName);
});
for(let location of locations){
selector.insertAdjacentHTML(
"beforeend",
`<option value="${location.stationId}">${location.locationFullName}</option>`
);
}
selector.addEventListener("change", (e)=>{
for(let location of cwbJson.records.location){
if(location.stationId != selector.value) continue;
/* "TEMP" stands for temperature, "HUMD" stands for humidity*/
displayWeather(
parseFloat(location.weatherElement["TEMP"]),
parseFloat(location.weatherElement["HUMD"])
);
/*changeWallpaper();*/
}
});
}catch(e){
let errNote = document.querySelector("#error");
errNote.innerHTML = e;
errNote.style["display"] = "";
}
}, {once: true});
</script>
<style>
#error{
background-color: #FF0000;
color: #FFF;
text-align: center;
padding: 0.5em;
}
/*input, select, button, textarea...*/
/*styles*/
input, select, button, textarea{
/*en-transparent, sharpen & flatten*/
--bg-opacity: .6;
broder-radius: 0;
border-style: none;
background-color: hsla(0, 0%, 100%, var(--bg-opacity));
/*animation*/
transition: background-color .5s
}
/*animation*/
input:hover, select:hover, button:hover, textarea:hover{
--bg-opacity: 1;
}
html, body{
height: 100vh;
width: 100vw;
/*font-size: 20px;*/
}
main{
width: 100%;
height: 100%;
background-color: hsl(210, 75%, 75%);
background-image: url("https://picsum.photos/1080/1920");
background-repeat: no-repeat;
background-position: center bottom;
background-size: cover;
}
/*add spaces to most elements*/
p, div, input, select, button, textarea{
padding: 0.5em;
}
/*css reset*/
*{
boxo-sizing: border-box;
}
#locationNameSelector{
width: 100%;
}
#weatherInfo{
text-align: center;
}
.meter{
display: inline-block;
width: clamp(3em, 30%, min(9em, 70%));
padding: 0;
}
.meter .barContainer{
background-color: hsla(0, 100%, 100%, 60%);
height: calc(90vh - 3rem - 1rem); /*3rem left for selector, 1rem for the padding of #weatherInfo*/
padding: 0;
position: relative; /*it is like declare the edge for the childrens with "absolute" position*/
}
.meter .bar{
width: 100%;
height: calc(100% * var(--value));
background-color: #0F0;
padding: 0;
overflow: hidden;
position: absolute;
bottom: 0;
transition: height .5s;
color: white;
text-shadow: 2px 2px 2px #000;
}
.meter .label{
color: white;
text-shadow: 2px 2px 2px #000;
}
#weatherInfo .humidity.meter .bar{
background-color: #2968FFB0;
}
#weatherInfo .temperature.meter .bar{
background-color: #FF5A19B0;
}
</style>
</head>
<body>
<div id="error" style="display: none;"></div>
<main>
<select id="locationNameSelector"></select>
<div id="weatherInfo">
<div class="temperature meter">
<div class="barContainer">
<div class="bar"></div>
</div>
<div class="label">溫度</div>
</div>
<div class="humidity meter">
<div class="barContainer">
<div class="bar"></div>
</div>
<div class="label">溼度</div>
</div>
</div>
</main>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment