{{-- Columnas SVG server-rendered (una serie). Espera: $data = [['label' => '03/07', 'value' => 123, 'tip' => '...'], …] $color = hex de la serie $unit = sustantivo para el tooltip por defecto ('peticiones', 'usuarios') Specs: barras ≤24px con remate superior redondeado 4px (base cuadrada), grid hairline sólido, ticks limpios, etiqueta directa sólo en el máximo. --}} @php $values = array_column($data, 'value'); $n = count($data); $max = $n ? max($values) : 0; // Techo "limpio" del eje Y en 4 divisiones (1/2/5 × 10^k) if ($max <= 4) { $step = 1; $divs = max($max, 1); } else { $divs = 4; $raw = $max / $divs; $pow = pow(10, floor(log10($raw))); $step = 10 * $pow; foreach ([1, 2, 5] as $f) { if ($f * $pow >= $raw) { $step = $f * $pow; break; } } } $niceMax = $step * $divs; $W = 760; $H = 240; $padL = 46; $padR = 10; $padT = 16; $padB = 26; $plotW = $W - $padL - $padR; $plotH = $H - $padT - $padB; $baseY = $padT + $plotH; $band = $n ? $plotW / $n : $plotW; $barW = max(2, min(24, $band * 0.72)); $skip = max(1, (int) ceil($n / 12)); // densidad de etiquetas X $maxIdx = $max > 0 ? array_search($max, $values) : null; $fmt = fn ($v) => number_format($v, 0, ',', '.'); @endphp @if($max === 0)
Sin datos en este rango todavía.
@else {{-- Grid + ticks Y (hairline sólido, recesivo) --}} @for($t = 0; $t <= $divs; $t++) @php $y = $baseY - ($t * $step / $niceMax) * $plotH; @endphp {{ $fmt($t * $step) }} @endfor {{-- Columnas --}} @foreach($data as $i => $point) @php $v = $point['value']; $x = $padL + $i * $band + ($band - $barW) / 2; $barH = ($v / $niceMax) * $plotH; $topY = $baseY - $barH; $r = min(4, $barW / 2, $barH); $tip = $point['tip'] ?? ($point['label'] . ' — ' . $fmt($v) . ' ' . ($unit ?? '')); @endphp @if($v > 0) @endif {{-- Etiqueta directa: sólo el máximo --}} @if($i === $maxIdx) {{ $fmt($v) }} @endif {{-- Etiqueta X --}} @if($i % $skip === 0) {{ $point['label'] }} @endif {{-- Zona de hover (toda la banda, tooltip JS) --}} @endforeach @endif