Skip to content

Commit daf2a10

Browse files
committed
feat: aggiunta generazione immagine OG per la pagina Numeri e aggiornato il layout per utilizzarla
1 parent 5d41190 commit daf2a10

3 files changed

Lines changed: 100 additions & 1 deletion

File tree

docs/NOTE_TECNICHE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ npm run generate-og-images
2727
- Le immagini vengono salvate in `public/og-images/`
2828
- Ogni iniziativa ha un'immagine con nome `og-{id}.png`
2929
- L'immagine di default è `og-default.png`
30+
- L'immagine per la pagina Numeri è `og-numeri.png`
3031
- Le immagini sono 1200x630px (formato ottimale per social media)
3132

3233
### Verifica immagini OpenGraph

src/lib/og-image-generator.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,101 @@ function getCategoryColor(category: string): string {
8080
return colors[category.toUpperCase()] || '#3b82f6'; // default blue-500
8181
}
8282

83+
// Funzione per generare l'immagine OG della pagina Numeri
84+
export async function generateNumeriOGImage(outputPath: string, options: OGImageOptions = {}): Promise<void> {
85+
const opts = { ...defaultOptions, ...options };
86+
87+
const title = 'Numeri';
88+
const subtitle = 'Statistiche e analisi delle iniziative referendarie';
89+
const titleFontSize = 80;
90+
const subtitleFontSize = 36;
91+
const titleY = opts.height / 2 - 50;
92+
const subtitleY = opts.height / 2 + 20;
93+
const brandText = "Un'idea di onData";
94+
95+
const svgTemplate = `
96+
<svg width="${opts.width}" height="${opts.height}" xmlns="http://www.w3.org/2000/svg">
97+
<!-- Sfondo gradiente -->
98+
<defs>
99+
<linearGradient id="numericBg" x1="0%" y1="0%" x2="100%" y2="100%">
100+
<stop offset="0%" style="stop-color:#1e3a8a;stop-opacity:1" />
101+
<stop offset="100%" style="stop-color:#3730a3;stop-opacity:1" />
102+
</linearGradient>
103+
</defs>
104+
105+
<rect width="100%" height="100%" fill="url(#numericBg)" />
106+
107+
<!-- Elementi grafici decorativi -->
108+
<!-- Barre istogramma stilizzate -->
109+
<rect x="80" y="120" width="200" height="20" rx="10" fill="rgba(16, 185, 129, 0.6)" />
110+
<rect x="80" y="160" width="300" height="20" rx="10" fill="rgba(59, 130, 246, 0.6)" />
111+
<rect x="80" y="200" width="150" height="20" rx="10" fill="rgba(139, 92, 246, 0.6)" />
112+
113+
<!-- Lollipop chart stilizzato -->
114+
<line x1="900" y1="400" x2="1100" y2="400" stroke="rgba(255,255,255,0.3)" stroke-width="2"/>
115+
<circle cx="1100" cy="400" r="12" fill="#10b981" opacity="0.8"/>
116+
<line x1="900" y1="450" x2="1050" y2="450" stroke="rgba(255,255,255,0.3)" stroke-width="2"/>
117+
<circle cx="1050" cy="450" r="12" fill="#3b82f6" opacity="0.8"/>
118+
<line x1="900" y1="500" x2="980" y2="500" stroke="rgba(255,255,255,0.3)" stroke-width="2"/>
119+
<circle cx="980" cy="500" r="12" fill="#8b5cf6" opacity="0.8"/>
120+
121+
<!-- Icone numeriche -->
122+
<text x="900" y="180" font-family="system-ui, -apple-system, sans-serif" font-size="72" font-weight="bold" fill="rgba(255,255,255,0.2)">123</text>
123+
<text x="950" y="250" font-family="system-ui, -apple-system, sans-serif" font-size="48" font-weight="bold" fill="rgba(255,255,255,0.15)">45%</text>
124+
125+
<!-- Titolo principale -->
126+
<text x="60" y="${titleY}"
127+
font-family="system-ui, -apple-system, sans-serif"
128+
font-size="${titleFontSize}"
129+
font-weight="900"
130+
fill="${opts.textColor}">
131+
${title}
132+
</text>
133+
134+
<!-- Sottotitolo -->
135+
<text x="60" y="${subtitleY}"
136+
font-family="system-ui, -apple-system, sans-serif"
137+
font-size="${subtitleFontSize}"
138+
font-weight="400"
139+
fill="rgba(255,255,255,0.9)">
140+
${subtitle}
141+
</text>
142+
143+
<!-- Logo/Brand text -->
144+
<text x="${opts.width - 60}" y="${opts.height - 40}"
145+
text-anchor="end"
146+
font-family="system-ui, -apple-system, sans-serif"
147+
font-size="20"
148+
font-weight="500"
149+
fill="rgba(255,255,255,0.7)">
150+
${brandText}
151+
</text>
152+
153+
<!-- Elemento decorativo angolare -->
154+
<polygon points="0,0 100,0 0,100" fill="rgba(255,255,255,0.05)" />
155+
<polygon points="${opts.width},${opts.height} ${opts.width-100},${opts.height} ${opts.width},${opts.height-100}" fill="rgba(255,255,255,0.05)" />
156+
</svg>
157+
`;
158+
159+
try {
160+
const pngBuffer = await sharp(Buffer.from(svgTemplate))
161+
.png({
162+
quality: 90,
163+
compressionLevel: 6
164+
})
165+
.toBuffer();
166+
167+
const dir = outputPath.substring(0, outputPath.lastIndexOf('/'));
168+
mkdirSync(dir, { recursive: true });
169+
writeFileSync(outputPath, pngBuffer);
170+
171+
console.log(`✅ Immagine OG Numeri generata: ${outputPath}`);
172+
} catch (error) {
173+
console.error(`❌ Errore nella generazione dell'immagine Numeri:`, error);
174+
throw error;
175+
}
176+
}
177+
83178
export async function generateOGImage(
84179
initiative: Initiative,
85180
outputPath: string,
@@ -268,6 +363,9 @@ export async function generateAllOGImages(initiatives: Initiative[], outputDir:
268363
join(outputDir, 'og-default.png')
269364
);
270365

366+
// Genero l'immagine dedicata per la pagina Numeri
367+
await generateNumeriOGImage(join(outputDir, 'og-numeri.png'));
368+
271369
// Genero le immagini per ogni iniziativa
272370
const promises = initiatives.map(initiative =>
273371
generateOGImage(

src/pages/numeri.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ const activeInitiatives = initiatives.filter(initiative =>
6363
const baseUrl = import.meta.env.BASE_URL;
6464
---
6565

66-
<Layout title="Numeri - Iniziative Referendum" description="Statistiche e numeri delle iniziative referendarie">
66+
<Layout title="Numeri - Iniziative Referendum" description="Statistiche e numeri delle iniziative referendarie" ogImage="og-numeri.png">
6767
<div class="min-h-screen bg-gray-50">
6868
<!-- Header con pulsante torna alle iniziative e menu hamburger -->
6969
<header class="bg-white border-b border-gray-200 sticky top-0 z-10">

0 commit comments

Comments
 (0)