Skip to content

Commit 1a2435f

Browse files
feat(svg): add animate=false option for static exports (JhaSourav07#2029)
1 parent da83292 commit 1a2435f

5 files changed

Lines changed: 44 additions & 18 deletions

File tree

app/api/streak/route.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ export async function GET(request: Request) {
130130
const targetEntity = org || user;
131131
const borderParam = searchParams.get('border');
132132
const sanitizedBorder = borderParam ? borderParam.replace(/[^a-fA-F0-9]/g, '') : undefined;
133-
133+
const animate = searchParams.get('animate') !== 'false';
134134
const params: BadgeParams = {
135135
user: targetEntity,
136136
bg: isAutoTheme ? selectedTheme.bg : bg || selectedTheme.bg,
@@ -162,6 +162,7 @@ export async function GET(request: Request) {
162162
gradient,
163163
disable_particles,
164164
glow,
165+
animate,
165166
};
166167

167168
let calendar;

app/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22
import { trackUser } from '@/utils/tracking';
3-
3+
import InteractiveViewer from '@/components/InteractiveViewer';
44
import Link from 'next/link';
55
import { useRef, useState, useEffect } from 'react';
66
import { AnimatePresence, motion } from 'framer-motion';

lib/svg/generator.ts

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ function generateParticles(
7272
count: number,
7373
sf: number,
7474
autoTheme: boolean = false,
75-
color: string = ''
75+
color: string = '',
76+
animate: boolean = true
7677
): string {
7778
let particles = '';
7879
const numParticles = particleCount(count);
@@ -87,8 +88,14 @@ function generateParticles(
8788

8889
particles += `
8990
<circle ${fillAttr} cx="${x + offsetX}" cy="${y - height}" r="${1.5 * sf}" opacity="1" pointer-events="none">
91+
${
92+
animate
93+
? `
9094
<animate attributeName="cy" from="${y - height}" to="${y - height - Math.round(20 * sf)}" dur="1.5s" begin="${delay}s" repeatCount="indefinite" />
9195
<animate attributeName="opacity" from="1" to="0" dur="1.5s" begin="${delay}s" repeatCount="indefinite" />
96+
`
97+
: ''
98+
}
9299
</circle>
93100
`;
94101
}
@@ -247,7 +254,8 @@ function renderTowers(
247254
accent: string | string[],
248255
text: string,
249256
sf: number,
250-
isAutoTheme: boolean = false
257+
isAutoTheme: boolean = false,
258+
animate: boolean = true
251259
): string {
252260
let towers = '';
253261
const opacityMultipliers = [0.4, 0.6, 0.8, 1.0];
@@ -340,7 +348,7 @@ function renderTowers(
340348
towers += `
341349
<g transform="translate(${t.x}, ${t.y})">
342350
<g class="cp-tower interactive-tower" data-date="${escapeXML(t.date)}" data-count="${t.contributionCount}" data-metric="${escapeXML(metric)}" style="animation-delay: ${delay}s;">
343-
${t.isToday ? '<animate attributeName="opacity" values="1;0.4;1" dur="1.5s" repeatCount="indefinite" />' : ''}
351+
${animate && t.isToday ? '<animate attributeName="opacity" values="1;0.4;1" dur="1.5s" repeatCount="indefinite" />' : ''}
344352
<title>${escapeXML(t.tooltip)}</title>
345353
<path d="M0 ${10 - t.h} L0 10 L-16 0 L-16 ${-t.h} Z" ${leftFillAttr} fill-opacity="${leftFaceOpacity}" ${leftStrokeAttr} />
346354
<path d="M0 ${10 - t.h} L0 10 L16 0 L16 ${-t.h} Z" ${rightFillAttr} fill-opacity="${rightFaceOpacity}" ${rightStrokeAttr} />
@@ -359,7 +367,16 @@ function renderTowers(
359367
: pColorResolved.startsWith('#')
360368
? pColorResolved
361369
: `#${pColorResolved}`;
362-
towers += generateParticles(t.x, t.y, t.h, t.contributionCount, sf, isAutoTheme, pColor);
370+
towers += generateParticles(
371+
t.x,
372+
t.y,
373+
t.h,
374+
t.contributionCount,
375+
sf,
376+
isAutoTheme,
377+
pColor,
378+
animate
379+
);
363380
}
364381
}
365382
return towers;
@@ -483,6 +500,7 @@ export function generateSVG(
483500
): string {
484501
if (params.autoTheme) return generateAutoThemeSVG(stats, params, calendar);
485502

503+
const animate = params.animate ?? true;
486504
const safeUser = escapeXML(params.user || 'GitHub User');
487505
const bg = `#${sanitizeHexColor(params.bg, '0d1117')}`;
488506

@@ -522,7 +540,7 @@ export function generateSVG(
522540
computeTowers(calendar, params.scale, stats.todayDate, params.mode),
523541
sf
524542
);
525-
const towers = renderTowers(towerData, params, accent, text, sf, false);
543+
const towers = renderTowers(towerData, params, accent, text, sf, false, animate);
526544

527545
const mainAccent = Array.isArray(accent)
528546
? accent[accent.length - 1] || '00ffaa'
@@ -567,7 +585,7 @@ function generateAutoThemeSVG(
567585
const sf = getSizeScale(params.size);
568586
const radius = sanitizeRadius(params.radius, 8) * sf;
569587
const labels = getLabels(params.lang);
570-
588+
const animate = params.animate ?? true;
571589
const W = Math.round(SVG_WIDTH * sf);
572590
const H = Math.round(SVG_HEIGHT * sf);
573591
const towerData = scaleTowerData(
@@ -638,15 +656,21 @@ ${
638656
: ''
639657
}
640658
641-
<rect
642-
x="${s(100)}"
643-
y="${s(80)}"
644-
width="${s(400)}"
645-
height="${s(1)}"
646-
class="cp-accent-fill scan-line"
647-
fill-opacity="0.3"
648-
style="--scan-speed: ${params.speed || '8s'}; --scan-start: ${s(0)}px; --scan-end: ${s(240)}px;"
649-
/>
659+
${
660+
animate
661+
? `
662+
<rect
663+
x="${s(100)}"
664+
y="${s(80)}"
665+
width="${s(400)}"
666+
height="${s(1)}"
667+
class="cp-accent-fill scan-line"
668+
fill-opacity="0.3"
669+
style="--scan-speed: ${params.speed || '8s'}; --scan-start: ${s(0)}px; --scan-end: ${s(240)}px;"
670+
/>
671+
`
672+
: ''
673+
}
650674
</svg>
651675
`;
652676
}

types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ export interface BadgeParams {
213213
gradient?: boolean;
214214

215215
disable_particles?: boolean;
216+
animate?: boolean;
216217
glow?: boolean;
217218
}
218219

utils/time.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ describe('getSecondsUntilMidnightInTimezone', () => {
242242
{ tz: 'Etc/GMT-14', offset: 14, utcHour: 10, expectedLocalHour: 0 }, // UTC+14
243243
];
244244

245-
for (const { tz, utcHour, expectedLocalHour } of extremeOffsets) {
245+
for (const { tz, utcHour } of extremeOffsets) {
246246
// Set UTC time such that local time is exactly midnight
247247
vi.setSystemTime(new Date(Date.UTC(2024, 6, 15, utcHour, 0, 0)));
248248

0 commit comments

Comments
 (0)