can be improved.
This commit is contained in:
@@ -1,22 +1,25 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Dynamic Gradient Generator</title>
|
||||
<title>Generator</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Dynamic Gradient Generator</h1>
|
||||
<h1>Generator</h1>
|
||||
|
||||
<div id="modeDisplay" class="mode-display">Current Mode: Loading...</div>
|
||||
|
||||
<div class="controls">
|
||||
<button onclick="refreshImage()">Refresh Image</button>
|
||||
<button onclick="toggleAutoRefresh()" id="autoRefreshBtn">Start Auto-Refresh (30s)</button>
|
||||
<button onclick="currentMode === 'terrain' ? refreshTerrain() : refreshImage()" id="refreshBtn">Refresh Image</button>
|
||||
<button onclick="toggleAutoRefresh()" id="autoRefreshBtn">Start Auto-Refresh (5s)</button>
|
||||
<button onclick="switchMode()" id="switchModeBtn" style="display: none;">Switch Mode</button>
|
||||
<button onclick="showStats()" id="statsBtn">Show Performance Stats</button>
|
||||
<button onclick="clearStats()" id="clearStatsBtn">Clear Stats</button>
|
||||
</div>
|
||||
|
||||
<div class="image-container">
|
||||
<img id="gradientImage" src="./output/gradient.jxl" alt="Dynamic Gradient">
|
||||
<img id="displayImage" src="./output/display.jxl" alt="Dynamic Image">
|
||||
</div>
|
||||
|
||||
<div id="statsPanel" class="stats-panel" style="display: none;">
|
||||
|
||||
134
web/script.js
134
web/script.js
@@ -1,22 +1,62 @@
|
||||
let autoRefreshInterval = null;
|
||||
let currentMode = 'gradient';
|
||||
|
||||
function refreshImage() {
|
||||
const img = document.getElementById('gradientImage');
|
||||
img.classList.add('loading');
|
||||
const img = document.getElementById('displayImage');
|
||||
|
||||
const timestamp = new Date().getTime();
|
||||
//img.src = 'gradient.jxl?' + timestamp;
|
||||
img.src = './output/gradient.jxl';
|
||||
// Check if server has finished encoding
|
||||
fetch('/api/image-ready')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.ready) {
|
||||
performSmoothImageSwap();
|
||||
} else {
|
||||
// Try again in 1 second
|
||||
setTimeout(refreshImage, 1000);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error checking image status:', error);
|
||||
updateStatus('Error checking image status', 'error');
|
||||
});
|
||||
}
|
||||
|
||||
function performSmoothImageSwap() {
|
||||
const img = document.getElementById('displayImage');
|
||||
const newImage = new Image();
|
||||
|
||||
img.onload = function() {
|
||||
img.classList.remove('loading');
|
||||
updateStatus('Image refreshed at ' + new Date().toLocaleTimeString());
|
||||
newImage.onload = function() {
|
||||
// Crossfade transition
|
||||
img.style.opacity = '0';
|
||||
setTimeout(() => {
|
||||
img.src = './output/display.jxl';
|
||||
img.style.opacity = '1';
|
||||
updateStatus('Image refreshed at ' + new Date().toLocaleTimeString());
|
||||
}, 300);
|
||||
};
|
||||
|
||||
img.onerror = function() {
|
||||
img.classList.remove('loading');
|
||||
newImage.onerror = function() {
|
||||
updateStatus('Error loading image', 'error');
|
||||
};
|
||||
|
||||
// Load with cache busting only when we know it's ready
|
||||
newImage.src = './output/display.jxl?' + new Date().getTime();
|
||||
}
|
||||
|
||||
function refreshTerrain() {
|
||||
fetch('/api/refresh-terrain', { method: 'POST' })
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
refreshImage();
|
||||
} else {
|
||||
updateStatus('Error refreshing terrain', 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error refreshing terrain:', error);
|
||||
updateStatus('Error refreshing terrain', 'error');
|
||||
});
|
||||
}
|
||||
|
||||
function toggleAutoRefresh() {
|
||||
@@ -25,14 +65,64 @@ function toggleAutoRefresh() {
|
||||
if (autoRefreshInterval) {
|
||||
clearInterval(autoRefreshInterval);
|
||||
autoRefreshInterval = null;
|
||||
button.textContent = 'Start Auto-Refresh (30s)';
|
||||
button.textContent = 'Start Auto-Refresh';
|
||||
button.classList.remove('danger');
|
||||
updateStatus('Auto-refresh stopped');
|
||||
} else {
|
||||
autoRefreshInterval = setInterval(refreshImage, 30000);
|
||||
// Faster refresh for terrain (5 seconds)
|
||||
autoRefreshInterval = setInterval(currentMode === 'terrain' ? refreshTerrain : refreshImage, 100);
|
||||
button.textContent = 'Stop Auto-Refresh';
|
||||
button.classList.add('danger');
|
||||
updateStatus('Auto-refresh started (30s interval)');
|
||||
updateStatus('Auto-refresh started');
|
||||
}
|
||||
}
|
||||
|
||||
function switchMode() {
|
||||
fetch('/api/switch-mode', { method: 'POST' })
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
currentMode = data.mode;
|
||||
updateModeDisplay();
|
||||
refreshImage();
|
||||
updateStatus('Switched to ' + data.mode + ' mode');
|
||||
|
||||
// Restart auto-refresh if active
|
||||
if (autoRefreshInterval) {
|
||||
clearInterval(autoRefreshInterval);
|
||||
autoRefreshInterval = setInterval(currentMode === 'terrain' ? refreshTerrain : refreshImage, 5000);
|
||||
}
|
||||
} else {
|
||||
updateStatus('Error switching mode', 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error switching mode:', error);
|
||||
updateStatus('Error switching mode', 'error');
|
||||
});
|
||||
}
|
||||
|
||||
function updateModeDisplay() {
|
||||
const modeDisplay = document.getElementById('modeDisplay');
|
||||
const switchBtn = document.getElementById('switchModeBtn');
|
||||
const refreshBtn = document.getElementById('refreshBtn');
|
||||
|
||||
if (modeDisplay) {
|
||||
modeDisplay.textContent = 'Current Mode: ' + currentMode;
|
||||
}
|
||||
|
||||
if (switchBtn) {
|
||||
switchBtn.textContent = 'Switch to ' + (currentMode === 'gradient' ? 'Terrain' : 'Gradient');
|
||||
}
|
||||
|
||||
if (refreshBtn) {
|
||||
if (currentMode === 'terrain') {
|
||||
refreshBtn.textContent = 'Refresh Terrain';
|
||||
refreshBtn.onclick = refreshTerrain;
|
||||
} else {
|
||||
refreshBtn.textContent = 'Refresh Image';
|
||||
refreshBtn.onclick = refreshImage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +198,21 @@ function updateStatus(message, type = 'info') {
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
// Auto-refresh when page loads
|
||||
// Initialize on page load
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
refreshImage();
|
||||
// Check if we're in all mode and get current mode
|
||||
fetch('/api/current-mode')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.mode) {
|
||||
currentMode = data.mode;
|
||||
updateModeDisplay();
|
||||
}
|
||||
refreshImage();
|
||||
})
|
||||
.catch(error => {
|
||||
// If endpoint doesn't exist, we're not in all mode
|
||||
console.log('Not in all mode, using default');
|
||||
refreshImage();
|
||||
});
|
||||
});
|
||||
@@ -35,7 +35,6 @@ img {
|
||||
height: auto;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
img.loading {
|
||||
@@ -106,4 +105,12 @@ button.danger:hover {
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.mode-display {
|
||||
margin: 10px 0;
|
||||
padding: 10px;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user