/** * Render the legend to an SVG object * * @param RenderContext $ctx The context to use for rendering this legend * * @return DOMElement The SVG representation of this legend */ public function toSvg(RenderContext $ctx) { $outer = new Canvas('legend', new LayoutBox(0, 0, 100, 100)); $outer->getLayout()->setPadding(2, 2, 2, 2); $nrOfColumns = 4; $topstep = 10 / $nrOfColumns + 2; $top = 0; $left = 0; $lastLabelEndPos = -1; foreach ($this->dataset as $color => $text) { $leftstep = 100 / $nrOfColumns + strlen($text); // Make sure labels don't overlap each other while ($lastLabelEndPos >= $left) { $left += $leftstep; } // When a label is longer than the available space, use the next line if ($left + strlen($text) > 100) { $top += $topstep; $left = 0; } $colorBox = new Rect($left, $top, 2, 2); $colorBox->setFill($color)->setStrokeWidth(2); $colorBox->keepRatio(); $outer->addElement($colorBox); $textBox = new Text($left + 5, $top + 2, $text); $textBox->setFontSize('2em'); $outer->addElement($textBox); // readjust layout $lastLabelEndPos = $left + strlen($text); $left += $leftstep; } $svg = $outer->toSvg($ctx); return $svg; }
/** * Render the vertical axis * * @param RenderContext $ctx The context to use for rendering * @param DOMElement $group The DOMElement this axis will be added to */ private function renderVerticalAxis(RenderContext $ctx, DOMElement $group) { $line = new Line(0, 0, 0, 100); $line->setStrokeWidth(2); $group->appendChild($line->toSvg($ctx)); foreach ($this->yUnit as $label => $pos) { $pos = 100 - $pos; $tick = new Line(0, $pos, -1, $pos); $group->appendChild($tick->toSvg($ctx)); $labelField = new Text(-0.5, $pos + 0.5, $label); $labelField->setFontSize('1.8em')->setAlignment(Text::ALIGN_END); $group->appendChild($labelField->toSvg($ctx)); if ($this->drawXGrid) { $bgLine = new Line(0, $pos, 100, $pos); $bgLine->setStrokeWidth(0.5)->setStrokeColor('#343'); $group->appendChild($bgLine->toSvg($ctx)); } } if ($this->yLabel) { $axisLabel = new Text(-8, 50, $this->yLabel); $axisLabel->setFontSize('2em')->setAdditionalStyle(Text::ORIENTATION_VERTICAL)->setFontWeight('bold')->setAlignment(Text::ALIGN_MIDDLE); $group->appendChild($axisLabel->toSvg($ctx)); } }
/** * Draw the label handler and the text for this pie slice * * @param RenderContext $ctx The rendering context to use for coordinate translation * @param int $r The radius of the pie in absolute coordinates * * @return DOMElement The group DOMElement containing the handle and label */ private function drawDescriptionLabel(RenderContext $ctx, $r) { $group = $ctx->getDocument()->createElement('g'); $rOuter = ($ctx->xToAbsolute($this->outerCaptionBound) + $ctx->yToAbsolute($this->outerCaptionBound)) / 2; $addOffset = $rOuter - $r; if ($addOffset < 0) { $addOffset = 0; } list($x, $y) = $ctx->toAbsolute($this->x, $this->y); $midRadius = $this->startRadian + ($this->endRadian - $this->startRadian) / 2; list($offsetX, $offsetY) = $ctx->toAbsolute($this->captionOffset, $this->captionOffset); $midX = $x + intval(($offsetX + $r) / 2 * sin($midRadius)); $midY = $y - intval(($offsetY + $r) / 2 * cos($midRadius)); // Draw the handle $path = new Path(array($midX, $midY)); $midX += ($addOffset + $r / 1.8) * ($midRadius > M_PI ? -1 : 1); $path->append(array($midX, $midY))->toAbsolute(); $midX += intval($r / 2 * sin(M_PI / 9)) * ($midRadius > M_PI ? -1 : 1); $midY -= intval($r / 2 * cos(M_PI / 3)) * ($midRadius < M_PI * 1.4 && $midRadius > M_PI / 3 ? -1 : 1); if ($ctx->ytoRelative($midY) > 100) { $midY = $ctx->yToAbsolute(100); } elseif ($ctx->ytoRelative($midY) < 0) { $midY = $ctx->yToAbsolute($ctx->ytoRelative(100 + $midY)); } $path->append(array($midX, $midY)); $rel = $ctx->toRelative($midX, $midY); // Draw the text box $text = new Text($rel[0] + 1.5, $rel[1], $this->caption); $text->setFontSize('2.5em'); $text->setAlignment($midRadius > M_PI ? Text::ALIGN_END : Text::ALIGN_START); $group->appendChild($path->toSvg($ctx)); $group->appendChild($text->toSvg($ctx)); return $group; }
/** * Render the vertical axis * * @param RenderContext $ctx The context to use for rendering * @param DOMElement $group The DOMElement this axis will be added to */ private function renderVerticalAxis(RenderContext $ctx, DOMElement $group) { $steps = $this->ticksPerX($this->yUnit->getTicks(), $ctx->getNrOfUnitsY(), $this->minUnitsPerStep); $ticks = $this->ticksPerX($this->yUnit->getTicks(), $ctx->getNrOfUnitsY(), $this->minUnitsPerTick); // Steps should always be ticks if ($ticks !== $steps) { $steps = $ticks * 5; } /* $line = new Line(0, 0, 0, 100); $line->setStrokeWidth(2); $group->appendChild($line->toSvg($ctx)); */ $i = 0; foreach ($this->yUnit as $label => $pos) { $pos = 100 - $pos; if ($i % $ticks === 0) { // draw a tick //$tick = new Line(0, $pos, -1, $pos); //$group->appendChild($tick->toSvg($ctx)); } if ($i % $steps === 0) { // draw a step $labelField = new Text(-0.5, $pos + 0.5, $label); $labelField->setFontSize('2.5em')->setAlignment(Text::ALIGN_END); $group->appendChild($labelField->toSvg($ctx)); if ($this->drawXGrid) { $bgLine = new Line(0, $pos, 100, $pos); $bgLine->setStrokeWidth(0.5)->setStrokeColor('#BFBFBF'); $group->appendChild($bgLine->toSvg($ctx)); } } $i++; } if ($this->yLabel || $this->xLabel) { if ($this->yLabel && $this->xLabel) { $txt = $this->yLabel . ' / ' . $this->xLabel; } else { if ($this->xLabel) { $txt = $this->xLabel; } else { $txt = $this->yLabel; } } $axisLabel = new Text(50, -3, $txt); $axisLabel->setFontSize('2em')->setFontWeight('bold')->setAlignment(Text::ALIGN_MIDDLE); $group->appendChild($axisLabel->toSvg($ctx)); } }