Inital Commit
This commit is contained in:
218
show.html
Normal file
218
show.html
Normal file
@@ -0,0 +1,218 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Ambient SlideShow</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: "Roboto", sans-serif;
|
||||
}
|
||||
body {
|
||||
background: #000;
|
||||
color: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
.slideshow {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
}
|
||||
.slide {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background-position: center center;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
opacity: 0;
|
||||
transition: opacity 1.5s ease-in-out;
|
||||
}
|
||||
.visible {
|
||||
opacity: 1;
|
||||
}
|
||||
.overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(
|
||||
to top,
|
||||
rgba(0, 0, 0, 0.65) 0%,
|
||||
rgba(0, 0, 0, 0.0) 40%
|
||||
);
|
||||
pointer-events: none;
|
||||
}
|
||||
.info-bar {
|
||||
position: absolute;
|
||||
bottom: 40px;
|
||||
left: 40px;
|
||||
right: 40px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.left-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 25px;
|
||||
}
|
||||
.right-info {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
.weather {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size:2rem;
|
||||
opacity: 0.8;
|
||||
}
|
||||
.weather-icon {
|
||||
margin-top: 44px;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
.weather-text {
|
||||
padding-left: 5px;
|
||||
text-align: right;
|
||||
margin-top: 44px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
.info-bar-header{
|
||||
text-align: right;
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
margin-bottom: 0.4rem;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
.photo-GeoData {
|
||||
text-align: right;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 400;
|
||||
margin-bottom: 0.1rem;
|
||||
}
|
||||
.photo-Date {
|
||||
text-align: right;
|
||||
font-size: 1rem;
|
||||
opacity: 0.8;
|
||||
}
|
||||
.clock-time {
|
||||
font-size: 4rem;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
.clock-date {
|
||||
font-size: 2rem;
|
||||
opacity: 0.8;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="slideshow">
|
||||
<div id="photoA" class="slide visible" style="background-image:url('');"></div>
|
||||
<div id="photoB" class="slide" style="background-image:url('');"></div>
|
||||
<div class="overlay"></div>
|
||||
<div class="info-bar">
|
||||
<div class="left-info">
|
||||
<div class="clock">
|
||||
<div class="weather">
|
||||
<div></div>
|
||||
<img id="weather-icon" class="weather-icon" src="" alt="">
|
||||
<div id="weather-text" class="weather-text"></div>
|
||||
</div>
|
||||
<div class="clock-time" id="clock-time"></div>
|
||||
<div class="clock-date" id="clock-date"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-info">
|
||||
<div class="info-bar-header">Photo info:</div>
|
||||
<div class="photo-GeoData" id="photo-GeoData"></div>
|
||||
<div class="photo-Date" id="photo-Date"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
// --- Slideshow ---
|
||||
async function start() {
|
||||
const res = await fetch('/images.json');
|
||||
const images = await res.json();
|
||||
if (!images.length) return;
|
||||
|
||||
let index = 0;
|
||||
let showingA = true;
|
||||
|
||||
const photoA = document.getElementById('photoA');
|
||||
const photoB = document.getElementById('photoB');
|
||||
|
||||
// Start with A visible
|
||||
photoA.style.backgroundImage = 'url(' + images[index] + ')';
|
||||
photoA.classList.add('visible');
|
||||
photoInfo(images[index])
|
||||
document.getElementById('photo-Date').textContent = ""
|
||||
document.getElementById('photo-GeoData').textContent = ""
|
||||
setInterval(() => {
|
||||
index = (index + 1) % images.length;
|
||||
if (showingA) {
|
||||
photoB.style.backgroundImage = 'url(' + images[index] + ')';
|
||||
photoB.classList.add('visible');
|
||||
photoA.classList.remove('visible');
|
||||
} else {
|
||||
photoA.style.backgroundImage = 'url(' + images[index] + ')';
|
||||
photoA.classList.add('visible');
|
||||
photoB.classList.remove('visible');
|
||||
}
|
||||
photoInfo(images[index])
|
||||
showingA = !showingA;
|
||||
}, 5 * 60 * 1000);
|
||||
}
|
||||
start();
|
||||
|
||||
// --- Photo Info ---
|
||||
async function photoInfo(photo) {
|
||||
const response = await fetch('exif?file='+photo);
|
||||
const data = await response.json();
|
||||
let formatted = new Date(data.capture_date).toLocaleDateString(undefined, {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric'
|
||||
});
|
||||
if (typeof data.geo_data == 'undefined' || data.geo_data == null) {
|
||||
document.getElementById('photo-GeoData').textContent = ""
|
||||
}else if(typeof data.geo_data.GeoData.features[0].properties.name !== 'undefined' & data.geo_data.GeoData.features[0].properties.name !== null & data.geo_data.GeoData.features[0].properties.name !== 'undefined' ){
|
||||
document.getElementById('photo-GeoData').textContent = data.geo_data.GeoData.features[0].properties.name + " - " + data.geo_data.GeoData.features[0].properties.city+ ", " + data.geo_data.GeoData.features[0].properties.country;
|
||||
}else{
|
||||
document.getElementById('photo-GeoData').textContent = data.geo_data.GeoData.features[0].properties.city+ ", " + data.geo_data.GeoData.features[0].properties.country;
|
||||
}
|
||||
|
||||
document.getElementById('photo-Date').textContent = formatted;
|
||||
}
|
||||
|
||||
// --- Clock ---
|
||||
function updateClock() {
|
||||
const now = new Date();
|
||||
document.getElementById('clock-time').textContent =
|
||||
now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
||||
document.getElementById('clock-date').textContent =
|
||||
now.toLocaleDateString([], { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
|
||||
}
|
||||
updateClock();
|
||||
setInterval(updateClock, 1000);
|
||||
|
||||
// --- Weather ---
|
||||
async function loadWeather() {
|
||||
const response = await fetch('/weather');
|
||||
const data = await response.json();
|
||||
const temp = data.temperature;
|
||||
const icon = data.symbol;
|
||||
document.getElementById("weather-text").textContent = `${temp}°C`;
|
||||
document.getElementById("weather-icon").src =`${icon}`;
|
||||
}
|
||||
loadWeather();
|
||||
setInterval(loadWeather, 10 * 60 * 1000); // refresh every 10 min
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user