2.0
This commit is contained in:
11
Slideshow.py
11
Slideshow.py
@@ -1,14 +1,19 @@
|
|||||||
from flask import Flask, render_template
|
from flask import Flask, render_template, request
|
||||||
import os
|
import os
|
||||||
|
|
||||||
app = Flask(__name__, static_folder='Pictures')
|
app = Flask(__name__, static_folder='Pictures')
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def slideshow():
|
def slideshow():
|
||||||
image_folder = 'Pictures/lori_bondage'
|
base_folder = 'Pictures'
|
||||||
|
folders = [f for f in os.listdir(base_folder) if os.path.isdir(os.path.join(base_folder, f))]
|
||||||
|
|
||||||
|
selected = request.args.get('folder', 'test')
|
||||||
|
image_folder = os.path.join(base_folder, selected)
|
||||||
images = [f'/{image_folder}/{f}' for f in os.listdir(image_folder)
|
images = [f'/{image_folder}/{f}' for f in os.listdir(image_folder)
|
||||||
if f.lower().endswith(('png', 'jpg', 'jpeg', 'gif'))]
|
if f.lower().endswith(('png', 'jpg', 'jpeg', 'gif'))]
|
||||||
return render_template('slideshow.html', images=images)
|
|
||||||
|
return render_template('slideshow.html', images=images, folders=folders, selected=selected)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(debug=True)
|
app.run(debug=True)
|
||||||
|
|||||||
@@ -3,12 +3,22 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>Slideshow</title>
|
<title>Slideshow</title>
|
||||||
<style>
|
<style>
|
||||||
body { background:#111; color:#fff; text-align:center; }
|
body{background:#111;color:#fff;text-align:center;margin:0}
|
||||||
img { max-width:90vw; max-height:80vh; margin-top:2vh; }
|
h1{margin-top:2vh}
|
||||||
#controls { margin-top:2vh; }
|
img{max-width:90vw;max-height:80vh;margin-top:2vh}
|
||||||
button { padding:.6rem 1.1rem; font-size:1rem; margin:.2rem;
|
|
||||||
border:0; border-radius:.4rem; cursor:pointer; }
|
/* fill screen when the image itself is fullscreen */
|
||||||
#counter { margin-top: 1vh; font-size: 1.1rem; }
|
img:fullscreen{
|
||||||
|
width:100vw;
|
||||||
|
height:100vh;
|
||||||
|
object-fit:contain;
|
||||||
|
margin:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls{margin-top:2vh}
|
||||||
|
button{padding:.6rem 1.1rem;font-size:1rem;margin:.2rem;border:0;border-radius:.4rem;cursor:pointer}
|
||||||
|
|
||||||
|
#counter{margin-top:1vh;font-size:1.1rem}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -18,51 +28,87 @@
|
|||||||
|
|
||||||
<div id="controls">
|
<div id="controls">
|
||||||
<button id="prev">◀︎ Prev</button>
|
<button id="prev">◀︎ Prev</button>
|
||||||
<button id="toggle">Pause</button>
|
<button id="toggle">Start</button>
|
||||||
<button id="next">Next ▶︎</button>
|
<button id="next">Next ▶︎</button>
|
||||||
<button id="fullscreen">⛶ Fullscreen</button>
|
<button id="fullscreen">⛶ Fullscreen</button>
|
||||||
|
<button id="shuffle">Shuffle</button>
|
||||||
|
<select id="folder-select" onchange="changeFolder(this.value)">
|
||||||
|
{% for folder in folders %}
|
||||||
|
<option value="{{ folder }}" {% if folder == selected %}selected{% endif %}>{{ folder }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
<input id="delay" type="number" min="1" value="15" style="width:4rem" />
|
||||||
|
<label for="delay">sec</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="counter">1 / {{ images|length }}</div>
|
<div id="counter">1 / {{ images|length }}</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const images = {{ images|tojson }};
|
const images = {{ images|tojson }};
|
||||||
const img = document.getElementById('slide');
|
const img = document.getElementById('slide');
|
||||||
const btnT = document.getElementById('toggle');
|
const btnT = document.getElementById('toggle');
|
||||||
const btnF = document.getElementById('fullscreen');
|
const btnF = document.getElementById('fullscreen');
|
||||||
const counter = document.getElementById('counter');
|
const counter= document.getElementById('counter');
|
||||||
let i = 0, playing = true, timer = setInterval(next, 15000);
|
let i=0, playing=false, timer=null; //, timer=setInterval(next,15000);
|
||||||
|
let shuffled = false;
|
||||||
function show(n) {
|
let order = [...Array(images.length).keys()];
|
||||||
i = (n + images.length) % images.length;
|
|
||||||
img.src = images[i];
|
function show(n){
|
||||||
counter.textContent = `${i + 1} / ${images.length}`;
|
if (shuffled) n = order[(n+order.length)%order.length];
|
||||||
|
else n = (n+images.length)%images.length;
|
||||||
|
|
||||||
|
i = images.indexOf(images[n]);
|
||||||
|
img.src = images[n];
|
||||||
|
counter.textContent = `${i+1} / ${images.length}`;
|
||||||
}
|
}
|
||||||
function next() { show(i + 1); }
|
|
||||||
function prev() { show(i - 1); }
|
function toggleShuffle(){
|
||||||
|
shuffled = !shuffled;
|
||||||
document.getElementById('next').onclick = next;
|
document.getElementById('shuffle').textContent = shuffled ? 'Unshuffle' : 'Shuffle';
|
||||||
document.getElementById('prev').onclick = prev;
|
if(shuffled){
|
||||||
|
order = [...Array(images.length).keys()];
|
||||||
btnT.onclick = () => {
|
for (let j = order.length - 1; j > 0; j--) {
|
||||||
playing = !playing;
|
const k = Math.floor(Math.random() * (j + 1));
|
||||||
btnT.textContent = playing ? 'Pause' : 'Play';
|
[order[j], order[k]] = [order[k], order[j]];
|
||||||
if (playing) timer = setInterval(next, 15000);
|
}
|
||||||
else clearInterval(timer);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function next(){show(i+1)}
|
||||||
|
function prev(){show(i-1)}
|
||||||
|
|
||||||
|
document.getElementById('next').onclick=next;
|
||||||
|
document.getElementById('prev').onclick=prev;
|
||||||
|
document.getElementById('shuffle').onclick = toggleShuffle;
|
||||||
|
|
||||||
|
btnT.onclick=()=>{
|
||||||
|
playing=!playing;
|
||||||
|
btnT.textContent=playing?'Pause':'Play';
|
||||||
|
if(playing){
|
||||||
|
const delaySec = parseInt(document.getElementById('delay').value, 10) || 15;
|
||||||
|
timer = setInterval(next, delaySec * 1000);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
clearInterval(timer);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
btnF.onclick = () => {
|
btnF.onclick=()=>{
|
||||||
if (!document.fullscreenElement) {
|
if(!document.fullscreenElement){
|
||||||
document.documentElement.requestFullscreen();
|
img.requestFullscreen(); // only the picture goes fullscreen
|
||||||
} else {
|
}else{
|
||||||
document.exitFullscreen();
|
document.exitFullscreen();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener('keydown', e => {
|
document.addEventListener('keydown',e=>{
|
||||||
if (e.key === 'ArrowRight') next();
|
if(e.key==='ArrowRight')next();
|
||||||
if (e.key === 'ArrowLeft') prev();
|
if(e.key==='ArrowLeft') prev();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function changeFolder(folder){
|
||||||
|
window.location.href = "/?folder=" + encodeURIComponent(folder);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user