🎨 Integrazione Texture Reali

Sistema completo per gestire texture fotografiche nel configuratore

📋 Overview del Sistema

Il sistema di gestione texture permette di utilizzare fotografie reali dei tessuti nel configuratore, mantenendo proporzioni corrette e performance ottimali.

1
Fotografia

Scatta foto dei tessuti

2
Processamento

Ottimizza e crea pattern

3
Integrazione

Carica nel configuratore

4
Applicazione

Visualizza sulla camicia

🚀 Implementazione Rapida

1. Struttura File Consigliata

project/ ├── index.html ├── js/ │ └── configurator.js ├── textures/ │ ├── originals/ // Immagini originali ad alta risoluzione │ │ ├── cotton-white-hd.jpg │ │ ├── oxford-blue-hd.jpg │ │ └── linen-beige-hd.jpg │ ├── processed/ // Pattern ottimizzati per web │ │ ├── cotton-white.jpg // 500x500px, seamless │ │ ├── oxford-blue.jpg │ │ └── linen-beige.jpg │ └── thumbnails/ // Anteprime per UI │ ├── cotton-white-thumb.jpg │ ├── oxford-blue-thumb.jpg │ └── linen-beige-thumb.jpg

2. Database Texture JSON

const textureDatabase = { "fabrics": [ { "id": "cotton-white-001", "name": "Cotone Bianco Oxford", "category": "cotone", "price": 59, "texture": { "image": "textures/processed/cotton-white.jpg", "thumbnail": "textures/thumbnails/cotton-white-thumb.jpg", "scale": 100, // Scala di default del pattern "rotation": 0, // Rotazione in gradi "seamless": true, // Se il pattern è seamless "resolution": "500x500" }, "properties": { "weight": "120g/m²", "composition": "100% Cotone", "weave": "Oxford", "stretch": false, "iron": "easy-iron" }, "colors": { "primary": "#ffffff", "secondary": "#f8f9fa" } }, { "id": "oxford-blue-002", "name": "Oxford Azzurro", "category": "cotone", "price": 59, "texture": { "image": "textures/processed/oxford-blue.jpg", "thumbnail": "textures/thumbnails/oxford-blue-thumb.jpg", "scale": 100, "rotation": 0, "seamless": true, "resolution": "500x500" } // ... altre proprietà } ] };

3. Classe TextureManager

class TextureManager { constructor() { this.loadedTextures = new Map(); this.currentTexture = null; } // Pre-carica tutte le texture per performance ottimali async preloadTextures(textureList) { const promises = textureList.map(async (texture) => { const img = new Image(); img.crossOrigin = 'anonymous'; return new Promise((resolve, reject) => { img.onload = () => { this.loadedTextures.set(texture.id, { image: img, data: texture }); resolve(); }; img.onerror = reject; img.src = texture.texture.image; }); }); await Promise.all(promises); console.log(`✅ Caricate ${this.loadedTextures.size} texture`); } // Applica texture all'SVG applyTexture(textureId, svgElement) { const texture = this.loadedTextures.get(textureId); if (!texture) return; // Trova o crea il pattern SVG let defs = svgElement.querySelector('defs'); if (!defs) { defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs'); svgElement.prepend(defs); } // Rimuovi pattern esistente const existingPattern = defs.querySelector('#fabric-pattern'); if (existingPattern) existingPattern.remove(); // Crea nuovo pattern const pattern = this.createSVGPattern(texture); defs.appendChild(pattern); // Applica a tutti gli elementi della camicia const shirtParts = svgElement.querySelectorAll('.fabric-fill'); shirtParts.forEach(part => { part.setAttribute('fill', 'url(#fabric-pattern)'); }); this.currentTexture = textureId; } // Crea pattern SVG da texture createSVGPattern(texture) { const pattern = document.createElementNS('http://www.w3.org/2000/svg', 'pattern'); pattern.setAttribute('id', 'fabric-pattern'); pattern.setAttribute('patternUnits', 'userSpaceOnUse'); // Calcola dimensioni pattern basate sulla scala const baseSize = 50; // Dimensione base in unità SVG const scale = texture.data.texture.scale / 100; const size = baseSize * scale; pattern.setAttribute('width', size); pattern.setAttribute('height', size); // Applica trasformazioni if (texture.data.texture.rotation) { pattern.setAttribute('patternTransform', `rotate(${texture.data.texture.rotation})`); } // Crea elemento image const image = document.createElementNS('http://www.w3.org/2000/svg', 'image'); image.setAttribute('href', texture.data.texture.image); image.setAttribute('width', size); image.setAttribute('height', size); pattern.appendChild(image); return pattern; } // Aggiusta scala del pattern in tempo reale adjustScale(scaleFactor) { const pattern = document.querySelector('#fabric-pattern'); if (!pattern) return; const currentWidth = parseFloat(pattern.getAttribute('width')); const newWidth = currentWidth * scaleFactor; pattern.setAttribute('width', newWidth); pattern.setAttribute('height', newWidth); const image = pattern.querySelector('image'); image.setAttribute('width', newWidth); image.setAttribute('height', newWidth); } } // Utilizzo const textureManager = new TextureManager(); await textureManager.preloadTextures(textureDatabase.fabrics); textureManager.applyTexture('cotton-white-001', document.querySelector('#shirt-svg'));

⚙️ Ottimizzazione Performance

Strategie Chiave

🖼️

Compressione Intelligente

  • JPG 80-85% qualità
  • Max 500x500px per pattern
  • WebP per browser moderni

Lazy Loading

  • Carica solo texture visibili
  • Preload on hover
  • Cache browser ottimizzata
🎯

Pattern Seamless

  • Bordi perfettamente allineati
  • Nessuna discontinuità visibile
  • Dimensioni potenze di 2

Script Batch Processing (Node.js)

const sharp = require('sharp'); const fs = require('fs').promises; const path = require('path'); async function processTextures(inputDir, outputDir) { const files = await fs.readdir(inputDir); for (const file of files) { if (!file.match(/\.(jpg|jpeg|png)$/i)) continue; const inputPath = path.join(inputDir, file); const basename = path.basename(file, path.extname(file)); // Genera pattern ottimizzato await sharp(inputPath) .resize(500, 500, { fit: 'cover', position: 'centre' }) .jpeg({ quality: 85, progressive: true }) .toFile(path.join(outputDir, 'processed', `${basename}.jpg`)); // Genera thumbnail await sharp(inputPath) .resize(150, 150, { fit: 'cover' }) .jpeg({ quality: 70 }) .toFile(path.join(outputDir, 'thumbnails', `${basename}-thumb.jpg`)); console.log(`✅ Processato: ${basename}`); } } // Esegui processTextures('./textures/originals', './textures');

📊 Specifiche Tecniche Pattern

Parametro Valore Consigliato Note
Dimensioni 500x500px Bilancia qualità e performance
Formato JPG o WebP JPG per compatibilità, WebP per modernità
Qualità 80-85% Ottimale per texture tessuti
DPI 72-150 Web standard
Peso File < 100KB Per caricamento rapido
Seamless Bordi devono combaciare perfettamente

🎯 Mappatura Texture su Camicia

Sistema di Coordinate UV

Importante: Per mantenere proporzioni realistiche, diverse parti della camicia possono richiedere scale diverse del pattern.
const shirtMapping = { "body": { "scale": 1.0, // Scala standard "rotation": 0, // Nessuna rotazione "offsetX": 0, "offsetY": 0 }, "sleeves": { "scale": 0.9, // Leggermente più piccolo "rotation": 0, "offsetX": 25, // Offset per continuità "offsetY": 0 }, "collar": { "scale": 0.8, // Più piccolo per dettaglio "rotation": 0, "offsetX": 0, "offsetY": 10 }, "cuffs": { "scale": 0.7, "rotation": 90, // Rotazione per polsini "offsetX": 0, "offsetY": 0 }, "pocket": { "scale": 0.6, "rotation": 0, "offsetX": 15, // Allineamento con corpo "offsetY": 30 } }; // Applica mapping differenziato function applyMappedTexture(svgElement, textureId, partName) { const mapping = shirtMapping[partName]; const part = svgElement.querySelector(`.shirt-${partName}`); if (!part || !mapping) return; // Crea pattern specifico per questa parte const patternId = `pattern-${partName}`; const pattern = createPatternForPart(textureId, mapping, patternId); // Aggiungi al defs svgElement.querySelector('defs').appendChild(pattern); // Applica al componente part.setAttribute('fill', `url(#${patternId})`); }

✨ Tips & Tricks Avanzati

1. Creazione Pattern Seamless con Photoshop

  1. Apri immagine texture (almeno 1000x1000px)
  2. Filter → Other → Offset
    • Horizontal: +250px
    • Vertical: +250px
    • Wrap Around: ✓
  3. Usa Clone Stamp per eliminare le giunture visibili
  4. Filter → Other → Offset di nuovo (-250px) per verificare
  5. Esporta come JPG 85% qualità

2. Testing Pattern Live

// Console tool per test rapido texture function testTexture(imageUrl) { const svg = document.querySelector('#shirt-svg'); const pattern = svg.querySelector('#fabric-pattern image'); if (pattern) { pattern.setAttribute('href', imageUrl); console.log('✅ Texture applicata!'); } } // Test con URL esterno testTexture('https://example.com/my-texture.jpg'); // Test con base64 const fileInput = document.querySelector('#texture-upload'); fileInput.onchange = (e) => { const reader = new FileReader(); reader.onload = (event) => testTexture(event.target.result); reader.readAsDataURL(e.target.files[0]); };

3. Gestione Memoria e Cache

Attenzione: Con molte texture ad alta risoluzione, gestisci attentamente la memoria.
class TextureCache { constructor(maxSize = 10) { this.cache = new Map(); this.maxSize = maxSize; } add(key, value) { // Rimuovi più vecchio se supera il limite if (this.cache.size >= this.maxSize) { const firstKey = this.cache.keys().next().value; this.cache.delete(firstKey); } this.cache.set(key, value); } get(key) { const value = this.cache.get(key); // LRU: sposta in fondo se usato if (value) { this.cache.delete(key); this.cache.set(key, value); } return value; } clear() { this.cache.clear(); } }

🚀 Prossimi Passi

Setup Completo in 5 Minuti:
  1. Copia il codice del TextureManager
  2. Prepara le tue texture (500x500px JPG)
  3. Crea il database JSON con i tuoi tessuti
  4. Integra nel configuratore esistente
  5. Testa con texture di esempio

Risorse Utili