From 4a59ff6712f67db924e190c7989caaacb1fdcf44 Mon Sep 17 00:00:00 2001 From: Matthias Jentsch Date: Wed, 27 Aug 2014 13:51:52 +0200 Subject: [PATCH] Support preserveAspectRatio in SVGRenderer Add support for the preserveAspectRatio attributes in root SVG elements, to improve the handling of padding and automatic resizing of inline SVG. --- library/Icinga/Chart/Chart.php | 18 +++++- library/Icinga/Chart/SVGRenderer.php | 92 ++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 1 deletion(-) diff --git a/library/Icinga/Chart/Chart.php b/library/Icinga/Chart/Chart.php index be436df2a..625a2ccaa 100644 --- a/library/Icinga/Chart/Chart.php +++ b/library/Icinga/Chart/Chart.php @@ -15,6 +15,8 @@ use Icinga\Chart\SVGRenderer; */ abstract class Chart implements Drawable { + protected $align = false; + /** * SVG renderer that handles * @@ -98,8 +100,22 @@ abstract class Chart implements Drawable throw new Exception('Dataset for graph doesn\'t have the proper structure'); } $this->build(); - + if ($this->align) { + $this->renderer->preserveAspectRatio(); + $this->renderer->setXAspectRatioAlignment(SVGRenderer::X_ASPECT_RATIO_MIN); + $this->renderer->setYAspectRatioAlignment(SVGRenderer::Y_ASPECT_RATIO_MIN); + } $this->renderer->getCanvas()->addElement($this); return $this->renderer->render(); } + + /** + * Align the chart to the top left corner instead of centering it + * + * @param bool $align + */ + public function alignTopLeft ($align = true) + { + $this->align = $align; + } } diff --git a/library/Icinga/Chart/SVGRenderer.php b/library/Icinga/Chart/SVGRenderer.php index 390e48739..69a3ce285 100644 --- a/library/Icinga/Chart/SVGRenderer.php +++ b/library/Icinga/Chart/SVGRenderer.php @@ -19,6 +19,22 @@ use Icinga\Chart\Primitive\Canvas; */ class SVGRenderer { + const X_ASPECT_RATIO_MIN = 'xMin'; + + const X_ASPECT_RATIO_MID = 'xMid'; + + const X_ASPECT_RATIO_MAX = 'xMax'; + + const Y_ASPECT_RATIO_MIN = 'YMin'; + + const Y_ASPECT_RATIO_MID = 'YMid'; + + const Y_ASPECT_RATIO_MAX = 'YMax'; + + const ASPECT_RATIO_PAD = 'meet'; + + const ASPECT_RATIO_CUTOFF = 'slice'; + /** * The XML-document * @@ -54,6 +70,35 @@ class SVGRenderer */ private $height = 100; + /** + * Whether the aspect ratio is preversed + * + * @var bool + */ + private $preserveAspectRatio = false; + + /** + * Horizontal alignment of SVG element + * + * @var string + */ + private $xAspectRatio = self::X_ASPECT_RATIO_MID; + + /** + * Vertical alignment of SVG element + * + * @var string + */ + private $yAspectRatio = self::Y_ASPECT_RATIO_MID; + + /** + * Define whether aspect differences should be handled using padding (default) or cutoff + * + * @var string + */ + private $xFillMode = "meet"; + + /** * Create the root document and the SVG root node */ @@ -92,6 +137,17 @@ class SVGRenderer $ctx->getNrOfUnitsY() ) ); + if ($this->preserveAspectRatio) { + $svg->setAttribute( + 'preserveAspectRatio', + sprintf ( + '%s%s %s', + $this->xAspectRatio, + $this->yAspectRatio, + $this->xFillMode + ) + ); + } return $svg; } @@ -141,4 +197,40 @@ class SVGRenderer { return $this->rootCanvas; } + + /** + * Preserve the aspect ratio of the rendered object + * + * Do not deform the content of the SVG when the aspect ratio of the viewBox + * differs from the aspect ratio of the SVG element, but add padding or cutoff + * instead + * + * @param bool $preserve Whether the aspect ratio should be preserved + */ + public function preserveAspectRatio($preserve = true) + { + $this->preserveAspectRatio = $preserve; + } + + /** + * Change the horizontal alignment of the SVG element + * + * Change the horizontal alignment of the svg, when preserveAspectRatio is used and + * padding is present. Defaults to + */ + public function setXAspectRatioAlignment($alignment) + { + $this->xAspectRatio = $alignment; + } + + /** + * Change the vertical alignment of the SVG element + * + * Change the vertical alignment of the svg, when preserveAspectRatio is used and + * padding is present. + */ + public function setYAspectRatioAlignment($alignment) + { + $this->yAspectRatio = $alignment; + } }