diff --git a/package.json b/package.json index 1048b52..178db69 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "lint": "eslint .", "preview": "vite preview", "optimize-images": "node scripts/optimize-images.js", + "create-thumbnails": "node scripts/create-thumbnails.js", "analyze": "node scripts/analyze-bundle.js" }, "dependencies": { diff --git a/public/images/projects/cloud_1_thumb.webp b/public/images/projects/cloud_1_thumb.webp new file mode 100644 index 0000000..80f35ba Binary files /dev/null and b/public/images/projects/cloud_1_thumb.webp differ diff --git a/public/images/projects/cub3d_thumb.webp b/public/images/projects/cub3d_thumb.webp new file mode 100644 index 0000000..8f57cd1 Binary files /dev/null and b/public/images/projects/cub3d_thumb.webp differ diff --git a/public/images/projects/homemade_nas_thumb.webp b/public/images/projects/homemade_nas_thumb.webp new file mode 100644 index 0000000..97bc8c2 Binary files /dev/null and b/public/images/projects/homemade_nas_thumb.webp differ diff --git a/public/images/projects/minishell_thumb.webp b/public/images/projects/minishell_thumb.webp new file mode 100644 index 0000000..1522bbb Binary files /dev/null and b/public/images/projects/minishell_thumb.webp differ diff --git a/public/images/projects/pong_thumb.webp b/public/images/projects/pong_thumb.webp new file mode 100644 index 0000000..6fc7ee6 Binary files /dev/null and b/public/images/projects/pong_thumb.webp differ diff --git a/public/images/sites/avopieces/mookup/3-devices-white (1)_thumb.webp b/public/images/sites/avopieces/mookup/3-devices-white (1)_thumb.webp new file mode 100644 index 0000000..750a13c Binary files /dev/null and b/public/images/sites/avopieces/mookup/3-devices-white (1)_thumb.webp differ diff --git a/public/images/sites/etsidemain/mookup/3-devices-white_thumb.webp b/public/images/sites/etsidemain/mookup/3-devices-white_thumb.webp new file mode 100644 index 0000000..25dfeae Binary files /dev/null and b/public/images/sites/etsidemain/mookup/3-devices-white_thumb.webp differ diff --git a/scripts/create-thumbnails.js b/scripts/create-thumbnails.js new file mode 100644 index 0000000..2ccce69 --- /dev/null +++ b/scripts/create-thumbnails.js @@ -0,0 +1,83 @@ +import sharp from 'sharp'; +import { readdir, stat } from 'fs/promises'; +import { join, extname, dirname, basename } from 'path'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const publicDir = join(__dirname, '..', 'public', 'images'); + +// Liste des images utilisées dans les cartes projet (miniatures) +const thumbnailImages = [ + 'projects/homemade_nas.webp', + 'projects/pong.webp', + 'projects/cloud_1.webp', + 'projects/minishell.webp', + 'projects/cub3d.webp', + 'sites/avopieces/mookup/3-devices-white (1).webp', + 'sites/etsidemain/mookup/3-devices-white.webp' +]; + +async function createThumbnail(filePath, size = 128) { + const ext = extname(filePath); + const dir = dirname(filePath); + const name = basename(filePath, ext); + const thumbnailPath = join(dir, `${name}_thumb${ext}`); + + try { + const stats = await stat(filePath); + const originalSize = stats.size; + + // Créer une miniature carrée de 128x128 + await sharp(filePath) + .resize(size, size, { + fit: 'cover', + position: 'center' + }) + .webp({ + quality: 85, + effort: 6 + }) + .toFile(thumbnailPath); + + const newStats = await stat(thumbnailPath); + const newSize = newStats.size; + const reduction = ((originalSize - newSize) / originalSize * 100).toFixed(2); + + console.log(`✅ ${basename(filePath)}`); + console.log(` Original: ${(originalSize / 1024).toFixed(2)} KB`); + console.log(` Miniature: ${(newSize / 1024).toFixed(2)} KB`); + console.log(` Réduction: ${reduction}%\n`); + + return { originalSize, newSize }; + } catch (error) { + console.error(`❌ Erreur avec ${filePath}:`, error.message); + return { originalSize: 0, newSize: 0 }; + } +} + +async function main() { + console.log('🖼️ Création des miniatures pour les cartes projet...\n'); + + let totalOriginal = 0; + let totalNew = 0; + + for (const imagePath of thumbnailImages) { + const fullPath = join(publicDir, imagePath); + const { originalSize, newSize } = await createThumbnail(fullPath); + totalOriginal += originalSize; + totalNew += newSize; + } + + const totalReduction = ((totalOriginal - totalNew) / totalOriginal * 100).toFixed(2); + + console.log('=' .repeat(50)); + console.log(`📊 RÉSUMÉ DES MINIATURES:`); + console.log(` Taille originale: ${(totalOriginal / 1024).toFixed(2)} KB`); + console.log(` Taille miniatures: ${(totalNew / 1024).toFixed(2)} KB`); + console.log(` Économie totale: ${totalReduction}%`); + console.log(` ${(totalOriginal - totalNew) / 1024} KB économisés! 🎉`); +} + +main().catch(console.error); diff --git a/src/components/ProjectCard.tsx b/src/components/ProjectCard.tsx index f4fde30..f770baa 100644 --- a/src/components/ProjectCard.tsx +++ b/src/components/ProjectCard.tsx @@ -28,22 +28,22 @@ export const ProjectCard = ({ title, description, icon, image, technologies, del whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }} transition={{ duration: 0.5, delay }} - whileHover={{ y: -5 }} + whileHover={{ y: -5, transition: { duration: 0.2 } }} onClick={handleClick} className={projectId ? "cursor-pointer" : ""} > - + {/* Indicateur cliquable en bas à droite */} {projectId && ( -
- +
+
)} {image && (
{`${title}