feat(modalidades): 6 ícones em falta, ícones animados, ícone centrado no cartão aberto
- Ícones novos (Bootcamp, YourFit Core, Run3070, Total Workout, On Ramp, Jump) do mesmo conjunto; só o LPO continua sem ícone no ficheiro de design. - Os ícones fitme-*.svg passam a ir embutidos (modalidade_icon_html): cada traço tem pathLength=1 e desenha-se ao aparecer, no hover e ao abrir o cartão; cada família tem um movimento (levantar, soco, respirar, saltar, chama, pedalar, correr). Outros ícones continuam <img>. - No cartão de detalhe (desktop) o ícone e o nome deslizam até ao centro vertical da coluna. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
42f5919915
commit
cb0e4540f2
10 files changed
+186
-8
No files matched your search
@@ -137,3 +137,42 @@ function site_tel(?string $phone): string {
|
||||
if ($p[0] !== '+' && str_starts_with($p, '00')) return '+' . substr($p, 2);
|
||||
return $p;
|
||||
}
|
||||
|
||||
// ─── Modalidade icon markup ───────────────────────────────────────────────────
|
||||
// The FitMe icon set (uploads/modalidades/icons/fitme-*.svg, shipped in the repo
|
||||
// — backoffice uploads are always named upl_*) is inlined so CSS can animate
|
||||
// the strokes: every drawable element gets pathLength="1" for the draw-in, and
|
||||
// the <svg> carries data-anim, a per-family movement (see style.css). Anything
|
||||
// else (legacy PNGs, uploaded SVGs) stays a plain <img>.
|
||||
function modalidade_icon_anim(string $slug): string {
|
||||
$map = [
|
||||
'lift' => ['yourfit-pump', 'crossfit', 'crossfit-teen-s', 'fbb', 'yourfit-core', 'total-workout'],
|
||||
'punch' => ['yourfit-fight', 'bootcamp'],
|
||||
'breathe' => ['yourfit-mind', 'yoga', 'pilates'],
|
||||
'bounce' => ['zumba', 'jump', 'yourfit-pulse', 'hybrid'],
|
||||
'flicker' => ['fitburn'],
|
||||
'ride' => ['cycling'],
|
||||
'run' => ['run3070', 'on-ramp', 'localizada'],
|
||||
];
|
||||
foreach ($map as $anim => $slugs) if (in_array($slug, $slugs, true)) return $anim;
|
||||
return 'lift';
|
||||
}
|
||||
|
||||
function modalidade_icon_html(?string $icon): string {
|
||||
$icon = trim((string) $icon);
|
||||
if ($icon === '') return '';
|
||||
if (preg_match('/^fitme-([a-z0-9-]+)\.svg$/', $icon, $m)) {
|
||||
$file = dirname(__DIR__) . '/uploads/modalidades/icons/' . $icon;
|
||||
$svg = is_file($file) ? (string) file_get_contents($file) : '';
|
||||
if (str_starts_with(ltrim($svg), '<svg')) {
|
||||
// Belt and braces: no scripts / event handlers, whatever the file says.
|
||||
$svg = preg_replace('~<script\b.*?</script>~is', '', $svg);
|
||||
$svg = preg_replace('~\son\w+\s*=\s*("[^"]*"|\'[^\']*\')~i', '', $svg);
|
||||
$svg = preg_replace('~\scolor="[^"]*"~', '', $svg, 1); // colour comes from CSS
|
||||
$svg = preg_replace('~<(path|circle|rect|line|polyline|polygon|ellipse)\b~', '<$1 pathLength="1"', $svg);
|
||||
$svg = preg_replace('~^\s*<svg\b~', '<svg class="mi" data-anim="' . modalidade_icon_anim($m[1]) . '" aria-hidden="true" focusable="false"', $svg, 1);
|
||||
return $svg;
|
||||
}
|
||||
}
|
||||
return '<img loading="lazy" draggable="false" src="' . htmlspecialchars(site_img_url($icon, 'uploads/modalidades/icons')) . '" alt="">';
|
||||
}
|
||||
Reference in new issue
Block a user