Implement progressive image loading in generateSite.js and enhance image serving with quality and width parameters. Added sharp dependency for image processing. Updated image display logic to improve user experience.
This commit is contained in:
parent
ba39cb4af7
commit
d575fd58e2
@ -47,13 +47,48 @@ async function generateSite() {
|
|||||||
<title>${image.description || `Image ${i + 1}`}</title>
|
<title>${image.description || `Image ${i + 1}`}</title>
|
||||||
<link rel="stylesheet" href="/styles.css">
|
<link rel="stylesheet" href="/styles.css">
|
||||||
<link rel="icon" type="image/png" href="/favicon.png">
|
<link rel="icon" type="image/png" href="/favicon.png">
|
||||||
|
<style>
|
||||||
|
.progressive-image-container {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.progressive-image {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
transition: opacity 0.5s ease-in-out;
|
||||||
|
}
|
||||||
|
.thumbnail {
|
||||||
|
filter: blur(10px);
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
.full-image {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
.full-image.loaded {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="image-container">
|
<div class="image-container">
|
||||||
${image?.localPath || 'No image URL available'
|
${image?.localPath ? `
|
||||||
? `<img src="${image?.localPath || 'No image URL available'}" alt="${image.metadata.description || ''}">`
|
<div class="progressive-image-container">
|
||||||
: '<p>Image not available</p>'
|
<img
|
||||||
}
|
class="progressive-image thumbnail"
|
||||||
|
src="${image.localPath}?quality=10&width=50"
|
||||||
|
alt="${image.metadata.description || ''}"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
class="progressive-image full-image"
|
||||||
|
src="${image.localPath}"
|
||||||
|
alt="${image.metadata.description || ''}"
|
||||||
|
onload="this.classList.add('loaded')"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
` : '<p>Image not available</p>'}
|
||||||
${image.description ? `<p class="description">${image.description}</p>` : ''}
|
${image.description ? `<p class="description">${image.description}</p>` : ''}
|
||||||
<div class="navigation">
|
<div class="navigation">
|
||||||
<a href="${prevFileName}">←</a>
|
<a href="${prevFileName}">←</a>
|
||||||
@ -86,11 +121,34 @@ async function generateSite() {
|
|||||||
async function serveStaticSite(port = 3000) {
|
async function serveStaticSite(port = 3000) {
|
||||||
const server = http.createServer(async (req, res) => {
|
const server = http.createServer(async (req, res) => {
|
||||||
try {
|
try {
|
||||||
|
// Parse URL and query parameters
|
||||||
|
const url = new URL(req.url, `http://localhost:${port}`);
|
||||||
|
const quality = url.searchParams.get('quality');
|
||||||
|
const width = url.searchParams.get('width');
|
||||||
|
|
||||||
// Convert URL to filesystem path
|
// Convert URL to filesystem path
|
||||||
let filePath;
|
let filePath;
|
||||||
if (req.url.startsWith('/images/')) {
|
if (url.pathname.startsWith('/images/')) {
|
||||||
// Serve directly from images folder
|
// Serve directly from images folder
|
||||||
filePath = req.url.slice(1); // Remove leading slash
|
filePath = url.pathname.slice(1); // Remove leading slash
|
||||||
|
|
||||||
|
// If quality parameter is present, serve a resized version
|
||||||
|
if (quality && width && (filePath.endsWith('.jpg') || filePath.endsWith('.jpeg') || filePath.endsWith('.png'))) {
|
||||||
|
try {
|
||||||
|
const Sharp = (await import('sharp')).default;
|
||||||
|
const image = await Sharp(filePath)
|
||||||
|
.resize(parseInt(width))
|
||||||
|
.jpeg({ quality: parseInt(quality) })
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
res.writeHead(200, { 'Content-Type': 'image/jpeg' });
|
||||||
|
res.end(image);
|
||||||
|
return;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error processing image:', error);
|
||||||
|
// Fall through to serve original image
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Serve from public folder
|
// Serve from public folder
|
||||||
filePath = path.join('public', req.url === '/' ? 'index.html' : req.url);
|
filePath = path.join('public', req.url === '/' ? 'index.html' : req.url);
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.7.9",
|
"axios": "^1.7.9",
|
||||||
"node-fetch": "^3.3.2"
|
"node-fetch": "^3.3.2",
|
||||||
|
"sharp": "^0.32.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user