diff options
Diffstat (limited to '')
-rw-r--r-- | library/Icinga/Chart/Graph/LineGraph.php | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/library/Icinga/Chart/Graph/LineGraph.php b/library/Icinga/Chart/Graph/LineGraph.php new file mode 100644 index 0000000..21f930a --- /dev/null +++ b/library/Icinga/Chart/Graph/LineGraph.php @@ -0,0 +1,202 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + + +namespace Icinga\Chart\Graph; + +use DOMElement; +use Icinga\Chart\Primitive\Drawable; +use Icinga\Chart\Primitive\Path; +use Icinga\Chart\Primitive\Circle; +use Icinga\Chart\Primitive\Styleable; +use Icinga\Chart\Render\RenderContext; + +/** + * LineGraph implementation for drawing a set of datapoints as + * a connected path + */ +class LineGraph extends Styleable implements Drawable +{ + /** + * The dataset to use + * + * @var array + */ + private $dataset; + + /** + * True to show dots for each datapoint + * + * @var bool + */ + private $showDataPoints = false; + + /** + * When true, the path will be discrete, i.e. showing hard steps instead of a direct line + * + * @var bool + */ + private $isDiscrete = false; + + /** + * The tooltips + * + * @var + */ + private $tooltips; + + /** @var array */ + private $graphs; + + /** @var int */ + private $order; + + /** + * The default stroke width + * @var int + */ + public $strokeWidth = 5; + + /** + * The size of the displayed dots + * + * @var int + */ + public $dotWith = 0; + + /** + * Create a new LineGraph displaying the given dataset + * + * @param array $dataset An array of [x, y] arrays to display + */ + public function __construct( + array $dataset, + array &$graphs, + $order, + array $tooltips = null + ) { + usort($dataset, array($this, 'sortByX')); + $this->dataset = $dataset; + $this->graphs = $graphs; + + $this->tooltips = $tooltips; + $ts = []; + foreach ($this->tooltips as $value) { + $ts[] = $value; + } + $this->tooltips = $ts; + $this->order = $order; + } + + /** + * Set datapoints to be emphased via dots + * + * @param bool $bool True to enable datapoints, otherwise false + */ + public function setShowDataPoints($bool) + { + $this->showDataPoints = $bool; + } + + /** + * Sort the daset by the xaxis + * + * @param array $v1 + * @param array $v2 + * @return int + */ + private function sortByX(array $v1, array $v2) + { + if ($v1[0] === $v2[0]) { + return 0; + } + return ($v1[0] < $v2[0]) ? -1 : 1; + } + + /** + * Configure this style + * + * @param array $cfg The configuration as given in the drawLine call + */ + public function setStyleFromConfig(array $cfg) + { + $fill = false; + foreach ($cfg as $elem => $value) { + if ($elem === 'color') { + $this->setStrokeColor($value); + } elseif ($elem === 'width') { + $this->setStrokeWidth($value); + } elseif ($elem === 'showPoints') { + $this->setShowDataPoints($value); + } elseif ($elem === 'fill') { + $fill = $value; + } elseif ($elem === 'discrete') { + $this->isDiscrete = true; + } + } + if ($fill) { + $this->setFill($this->strokeColor); + $this->setStrokeColor('black'); + } + } + + /** + * Render this BarChart + * + * @param RenderContext $ctx The rendering context to use for drawing + * + * @return DOMElement $dom Element + */ + public function toSvg(RenderContext $ctx) + { + $path = new Path($this->dataset); + if ($this->isDiscrete) { + $path->setDiscrete(true); + } + $path->setStrokeColor($this->strokeColor); + $path->setStrokeWidth($this->strokeWidth); + + $path->setAttribute('data-icinga-graph-type', 'line'); + if ($this->fill !== 'none') { + $firstX = $this->dataset[0][0]; + $lastX = $this->dataset[count($this->dataset)-1][0]; + $path->prepend(array($firstX, 100)) + ->append(array($lastX, 100)); + $path->setFill($this->fill); + } + + $path->setAdditionalStyle(['clip-path' => 'url(#clip)']); + $path->setId($this->id ?? uniqid('line-graph-')); + $group = $path->toSvg($ctx); + + foreach ($this->dataset as $x => $point) { + if ($this->showDataPoints === true) { + $dot = new Circle($point[0], $point[1], $this->dotWith); + $dot->setFill($this->strokeColor); + $group->appendChild($dot->toSvg($ctx)); + } + + // Draw invisible circle for tooltip hovering + if (isset($this->tooltips[$x])) { + $invisible = new Circle($point[0], $point[1], 20); + $invisible->setFill($this->strokeColor); + $invisible->setAdditionalStyle(['opacity' => '0.0']); + $data = array( + 'label' => isset($this->graphs[$this->order]['label']) ? + strtolower($this->graphs[$this->order]['label']) : '', + 'color' => isset($this->graphs[$this->order]['color']) ? + strtolower($this->graphs[$this->order]['color']) : '#fff' + ); + $format = isset($this->graphs[$this->order]['tooltip']) + ? $this->graphs[$this->order]['tooltip'] : null; + $title = $ctx->getDocument()->createElement('title'); + $title->textContent = $this->tooltips[$x]->renderNoHtml($this->order, $data, $format); + $invisibleRendered = $invisible->toSvg($ctx); + $invisibleRendered->appendChild($title); + $group->appendChild($invisibleRendered); + } + } + + return $group; + } +} |