diff --git a/README.md b/README.md index b6fc3b0f..cd81a13e 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,7 @@ If the `theme` parameter is specified, any color customizations specified will b | `exclude_days` | List of days of the week to exclude from streaks | Comma-separated list of day abbreviations (Sun, Mon, Tue, Wed, Thu, Fri, Sat) e.g. `Sun,Sat` | | `disable_animations` | Disable SVG animations (Default: `false`) | `true` or `false` | | `card_width` | Width of the card in pixels (Default: `495`) | Positive integer, minimum width is 100px per column | +| `card_height` | Height of the card in pixels (Default: `195`) | Positive integer, minimum height is 170px | | `hide_total_contributions` | Hide the total contributions (Default: `false`) | `true` or `false` | | `hide_current_streak` | Hide the current streak (Default: `false`) | `true` or `false` | | `hide_longest_streak` | Hide the longest streak (Default: `false`) | `true` or `false` | diff --git a/src/card.php b/src/card.php index d5ddc6d9..3e4cf61d 100644 --- a/src/card.php +++ b/src/card.php @@ -322,6 +322,19 @@ function getCardWidth(array $params, int $numColumns = 3): int return max($minimumWidth, intval($params["card_width"] ?? $defaultWidth)); } +/** + * Get the card height from params taking into account minimum and default values + * + * @param array $params Request parameters + * @return int Card width + */ +function getCardHeight(array $params): int +{ + $defaultHeight = 195; + $minimumHeight = 170; + return max($minimumHeight, intval($params["card_height"] ?? $defaultHeight)); +} + /** * Generate SVG output for a stats array * @@ -364,7 +377,11 @@ function generateCard(array $stats, array $params = null): string $rectWidth = $cardWidth - 1; $columnWidth = $numColumns > 0 ? $cardWidth / $numColumns : 0; - // offsets for the bars between columns + $cardHeight = getCardHeight($params); + $rectHeight = $cardHeight - 1; + $heightOffset = ($cardHeight - 195) / 2; + + // X offsets for the bars between columns $barOffsets = [-999, -999]; for ($i = 0; $i < $numColumns - 1; $i++) { $barOffsets[$i] = $columnWidth * ($i + 1); @@ -384,6 +401,22 @@ function generateCard(array $stats, array $params = null): string $currentStreakOffset = $showCurrentStreak ? $columnOffsets[$nextColumnIndex++] : -999; $longestStreakOffset = $showLongestStreak ? $columnOffsets[$nextColumnIndex++] : -999; + // Y offsets for the bars + $barHeightOffsets = [28 + $heightOffset / 2, 170 + $heightOffset]; + // Y offsets for the numbers and dates + $longestStreakHeightOffset = $totalContributionsHeightOffset = [ + 48 + $heightOffset, + 84 + $heightOffset, + 114 + $heightOffset, + ]; + $currentStreakHeightOffset = [ + 48 + $heightOffset, + 108 + $heightOffset, + 145 + $heightOffset, + 71 + $heightOffset, + 19.5 + $heightOffset, + ]; + // total contributions $totalContributions = $numFormatter->format($stats["totalContributions"]); $firstContribution = formatDate($stats["firstContribution"], $dateFormat, $localeCode); @@ -440,7 +473,7 @@ function generateCard(array $stats, array $params = null): string } return " + style='isolation: isolate' viewBox='0 0 {$cardWidth} {$cardHeight}' width='{$cardWidth}px' height='{$cardHeight}px' direction='{$direction}'> - + - + {$theme["backgroundGradient"]} - + - - + + - + {$totalContributions} - + {$totalContributionsText} - + {$totalContributionsRange} @@ -494,21 +527,21 @@ function generateCard(array $stats, array $params = null): string - + {$currentStreak} - + {$currentStreakText} - + {$currentStreakRange} @@ -516,10 +549,10 @@ function generateCard(array $stats, array $params = null): string - + - + @@ -527,21 +560,21 @@ function generateCard(array $stats, array $params = null): string - + {$longestStreak} - + {$longestStreakText} - + {$longestStreakRange} @@ -575,7 +608,13 @@ function generateErrorCard(string $message, array $params = null): string $rectWidth = $cardWidth - 1; $centerOffset = $cardWidth / 2; - return " + // read card_height parameter + $cardHeight = getCardHeight($params); + $rectHeight = $cardHeight - 1; + $heightOffset = ($cardHeight - 195) / 2; + $errorLabelOffset = $cardHeight / 2 + 10.5; + + return " - + {$theme["backgroundGradient"]} - + - + {$message} @@ -607,7 +646,7 @@ function generateErrorCard(string $message, array $params = null): string - + @@ -704,7 +743,7 @@ function ($matches) { * @param int $cardWidth The width of the card * @return string The generated PNG data */ -function convertSvgToPng(string $svg, int $cardWidth): string +function convertSvgToPng(string $svg, int $cardWidth, int $cardHeight): string { // trim off all whitespaces to make it a valid SVG string $svg = trim($svg); @@ -722,7 +761,7 @@ function convertSvgToPng(string $svg, int $cardWidth): string // `--export-filename -`: write output to stdout // `-w 495 -h 195`: set width and height of the output image // `--export-type png`: set the output format to PNG - $cmd = "echo {$svg} | inkscape --pipe --export-filename - -w {$cardWidth} -h 195 --export-type png"; + $cmd = "echo {$svg} | inkscape --pipe --export-filename - -w {$cardWidth} -h {$cardHeight} --export-type png"; // convert svg to png $png = shell_exec($cmd); // skipcq: PHP-A1009 @@ -772,7 +811,8 @@ function generateOutput(string|array $output, array $params = null): array try { // extract width from SVG $cardWidth = (int) preg_replace("/.*width=[\"'](\d+)px[\"'].*/", "$1", $svg); - $png = convertSvgToPng($svg, $cardWidth); + $cardHeight = (int) preg_replace("/.*height=[\"'](\d+)px[\"'].*/", "$1", $svg); + $png = convertSvgToPng($svg, $cardWidth, $cardHeight); return [ "contentType" => "image/png", "body" => $png, diff --git a/src/demo/index.php b/src/demo/index.php index 4da301c3..3a749372 100644 --- a/src/demo/index.php +++ b/src/demo/index.php @@ -170,6 +170,9 @@ function gtag() { + + +