Add ability to configure image slide interval

This commit is contained in:
2024-11-24 09:04:27 +11:00
parent 293d373fb3
commit 15a2fb5bd3
3 changed files with 227 additions and 4 deletions
BIN
View File
Binary file not shown.
+223 -4
View File
@@ -24,14 +24,35 @@
width: 100%;
height: 100%;
opacity: 0;
transition: opacity 0.5s ease-in-out;
transition: all 0.5s ease-in-out;
display: flex;
align-items: center;
justify-content: center;
transform: scale(1) rotate(0deg);
filter: blur(0px);
}
.slide.active {
opacity: 1;
}
/* Transition Effects */
.slide.fade-out {
opacity: 0;
}
.slide.slide-out {
transform: translateX(-100%);
}
.slide.scale-out {
transform: scale(0.8);
opacity: 0;
}
.slide.rotate-out {
transform: rotate(-15deg);
opacity: 0;
}
.slide.blur-out {
filter: blur(10px);
opacity: 0;
}
.slide img {
max-width: 100%;
max-height: 100%;
@@ -78,6 +99,35 @@
.control-button:hover {
background: rgba(255,255,255,0.2);
}
.control-group {
display: flex;
align-items: center;
gap: 0.5rem;
background: rgba(255,255,255,0.1);
padding: 0.5rem;
border-radius: 0.375rem;
}
.slider {
-webkit-appearance: none;
width: 100px;
height: 4px;
border-radius: 2px;
background: rgba(255,255,255,0.2);
outline: none;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
width: 16px;
height: 16px;
border-radius: 50%;
background: #3b82f6;
cursor: pointer;
}
#intervalValue {
color: white;
min-width: 30px;
font-size: 0.9rem;
}
.progress-circle {
position: fixed;
top: 1rem;
@@ -117,6 +167,51 @@
max-width: 400px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
}
.settings-panel {
position: fixed;
bottom: 5rem;
left: 50%;
transform: translateX(-50%);
background-color: rgba(0, 0, 0, 0.9);
padding: 1rem;
border-radius: 0.5rem;
display: none;
width: 90%;
max-width: 400px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
}
.settings-content {
max-height: 60vh;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
.settings-group {
margin: 1rem 0;
padding: 0.75rem;
background: rgba(255, 255, 255, 0.05);
border-radius: 0.375rem;
}
.settings-group h4 {
color: #fff;
margin: 0 0 0.5rem 0;
font-size: 0.9rem;
font-weight: 500;
opacity: 0.8;
}
.settings-item {
display: flex;
align-items: center;
gap: 1rem;
margin: 0.5rem 0;
}
.settings-item .slider {
flex: 1;
}
.settings-item span {
color: white;
min-width: 40px;
font-size: 0.9rem;
}
.playlist-content {
max-height: 60vh;
overflow-y: auto;
@@ -176,6 +271,34 @@
font-weight: 500;
text-align: center;
}
.transition-options {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
gap: 0.5rem;
}
.transition-option {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem;
background: rgba(255, 255, 255, 0.05);
border-radius: 0.375rem;
cursor: pointer;
transition: background-color 0.2s;
}
.transition-option:hover {
background: rgba(255, 255, 255, 0.1);
}
.transition-option input[type="radio"] {
width: 16px;
height: 16px;
margin: 0;
}
.transition-option label {
color: white;
font-size: 0.9rem;
cursor: pointer;
}
@media (max-width: 768px) {
.controls {
@@ -269,6 +392,13 @@
</svg>
<span>{% trans "Playlist" %}</span>
</button>
<button class="control-button" onclick="toggleSettings()">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
</svg>
<span>{% trans "Settings" %}</span>
</button>
<button class="control-button" onclick="exitSlideshow()">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
@@ -278,6 +408,44 @@
</div>
</div>
<div class="settings-panel">
<div class="settings-content">
<h3>{% trans "Slideshow Settings" %}</h3>
<div class="settings-group">
<h4>{% trans "Transition Interval" %}</h4>
<div class="settings-item">
<input type="range" class="slider" id="intervalSlider" min="2000" step="1000" max="15000" value="5000" oninput="updateInterval(this.value)">
<span id="intervalValue">5s</span>
</div>
</div>
<div class="settings-group">
<h4>{% trans "Transition Effect" %}</h4>
<div class="transition-options">
<div class="transition-option">
<input type="radio" id="effect-fade" name="transition-effect" value="fade" checked>
<label for="effect-fade">Fade</label>
</div>
<div class="transition-option">
<input type="radio" id="effect-slide" name="transition-effect" value="slide">
<label for="effect-slide">Slide</label>
</div>
<div class="transition-option">
<input type="radio" id="effect-scale" name="transition-effect" value="scale">
<label for="effect-scale">Scale</label>
</div>
<div class="transition-option">
<input type="radio" id="effect-rotate" name="transition-effect" value="rotate">
<label for="effect-rotate">Rotate</label>
</div>
<div class="transition-option">
<input type="radio" id="effect-blur" name="transition-effect" value="blur">
<label for="effect-blur">Blur</label>
</div>
</div>
</div>
</div>
</div>
<audio id="backgroundMusic">
<source src="" type="audio/mpeg">
Your browser does not support the audio element.
@@ -307,11 +475,12 @@ const totalSlides = slides.length;
let slideInterval = null;
let progressInterval = null;
let isPlaying = true;
const INTERVAL_TIME = 5000; // 5 seconds
let INTERVAL_TIME = 5000; // 5 seconds, configurable through slider
const CONTROLS_HIDE_DELAY = 6000; // 6 seconds
let startTime = null;
let animationFrame = null;
let controlsTimeout = null;
let currentEffect = 'fade';
const backgroundMusic = document.getElementById('backgroundMusic');
let isMusicPlaying = true;
@@ -485,23 +654,62 @@ function togglePlaylist() {
const playlistPanel = document.querySelector('.music-playlist');
if (playlistPanel.style.display === 'none' || playlistPanel.style.display === '') {
playlistPanel.style.display = 'block';
document.querySelector('.settings-panel').style.display = 'none';
} else {
playlistPanel.style.display = 'none';
}
}
function toggleSettings() {
const settingsPanel = document.querySelector('.settings-panel');
if (settingsPanel.style.display === 'none' || settingsPanel.style.display === '') {
settingsPanel.style.display = 'block';
document.querySelector('.music-playlist').style.display = 'none';
} else {
settingsPanel.style.display = 'none';
}
}
function selectSong(index) {
loadSong(index);
togglePlaylist();
}
function showSlide(index) {
slides.forEach(slide => slide.classList.remove('active'));
const oldSlide = slides[currentSlide];
currentSlide = (index + totalSlides) % totalSlides;
slides[currentSlide].classList.add('active');
const newSlide = slides[currentSlide];
// Remove any existing transition classes
oldSlide.classList.remove('active', 'fade-out', 'slide-out', 'scale-out', 'rotate-out', 'blur-out');
newSlide.classList.remove('fade-out', 'slide-out', 'scale-out', 'rotate-out', 'blur-out');
// Add the appropriate transition class
oldSlide.classList.add(`${currentEffect}-out`);
newSlide.classList.add('active');
resetProgress();
}
function updateTransitionEffect(effect) {
currentEffect = effect;
}
// Add event listeners for transition effects
document.addEventListener('DOMContentLoaded', async () => {
await fetchPlaylist();
startSlideshow();
// Initialize interval value display
document.getElementById('intervalValue').textContent = `${INTERVAL_TIME/1000}s`;
// Add transition effect listeners
document.querySelectorAll('input[name="transition-effect"]').forEach(radio => {
radio.addEventListener('change', (e) => {
updateTransitionEffect(e.target.value);
});
});
});
function nextSlide() {
showSlide(currentSlide + 1);
}
@@ -583,6 +791,15 @@ function resetProgress() {
}
}
function updateInterval(value) {
INTERVAL_TIME = parseInt(value);
document.getElementById('intervalValue').textContent = `${value / 1000}s`;
if (isPlaying) {
stopSlideshow();
startSlideshow();
}
}
// Keyboard controls
document.addEventListener('keydown', (e) => {
switch(e.key) {
@@ -617,6 +834,8 @@ document.addEventListener('keydown', (e) => {
document.addEventListener('DOMContentLoaded', async () => {
await fetchPlaylist();
startSlideshow();
// Initialize interval value display
document.getElementById('intervalValue').textContent = `${INTERVAL_TIME/1000}s`;
});
</script>
{% endblock %}
+4
View File
@@ -1811,6 +1811,10 @@ video {
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.outline {
outline-style: solid;
}
.blur {
--tw-blur: blur(8px);
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);