Skip to content

Commit b4a8f15

Browse files
Feat: adds crosses/ crossesAt options to axis component
1 parent 2b04ee5 commit b4a8f15

File tree

5 files changed

+126
-6
lines changed

5 files changed

+126
-6
lines changed

docs/usage/shapes/chart.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,32 @@ $shape->getPlotArea()->getAxisX()->setMinBounds(0);
9595
$shape->getPlotArea()->getAxisX()->setMaxBounds(200);
9696
```
9797

98+
#### Crossing
99+
100+
For Axis, you can define where it should be crossed by the perpendicular/ horizontal axis trought `setCrossesAt`.
101+
The property can be defined by one of the three given constants or as an absolute value on the target axis.
102+
103+
``` php
104+
use PhpOffice\PhpPresentation\Shape\Axis;
105+
106+
$bar = new Bar();
107+
108+
$shape = $slide->createChartShape();
109+
$shape->getPlotArea()->setType($bar);
110+
111+
// Usage of constant: Horizontal axis will cross the Y-Axis at `0`
112+
$shape->getPlotArea()->getAxisY()->setCrossesAt(Axis::CROSSES_AUTO);
113+
114+
// Usage of individual value: Horizontal axis will cross the Y-Axis at `3`
115+
$shape->getPlotArea()->getAxisY()->setCrossesAt('3');
116+
```
117+
118+
| Constant | Description |
119+
| -------------------- | ------------------------ |
120+
| `AXIS::CROSSES_AUTO` | Axis crosses at zero. |
121+
| `AXIS::CROSSES_MIN` | Axis crosses at minimum. |
122+
| `AXIS::CROSSES_MAX` | Axis crosses at maximum. |
123+
98124
#### Outline
99125

100126
You can define outline for each axis (X & Y).

src/PhpPresentation/Shape/Chart/Axis.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ class Axis implements ComparableInterface
3838
public const TICK_LABEL_POSITION_HIGH = 'high';
3939
public const TICK_LABEL_POSITION_LOW = 'low';
4040

41+
public const CROSSES_AUTO = 'autoZero';
42+
public const CROSSES_MIN = 'min';
43+
public const CROSSES_MAX = 'max';
44+
4145
/**
4246
* Title.
4347
*
@@ -84,6 +88,11 @@ class Axis implements ComparableInterface
8488
*/
8589
protected $maxBounds;
8690

91+
/**
92+
* @var string
93+
*/
94+
protected $crossesAt = self::CROSSES_AUTO;
95+
8796
/**
8897
* @var string
8998
*/
@@ -243,6 +252,26 @@ public function setMaxBounds(int $maxBounds = null): self
243252
return $this;
244253
}
245254

255+
/**
256+
* @return string
257+
*/
258+
public function getCrossesAt(): string
259+
{
260+
return $this->crossesAt;
261+
}
262+
263+
/**
264+
* @param string $value
265+
*
266+
* @return self
267+
*/
268+
public function setCrossesAt(string $value = self::CROSSES_AUTO): self
269+
{
270+
$this->crossesAt = $value;
271+
272+
return $this;
273+
}
274+
246275
public function getMajorGridlines(): ?Gridlines
247276
{
248277
return $this->majorGridlines;

src/PhpPresentation/Writer/PowerPoint2007/PptCharts.php

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2297,15 +2297,17 @@ protected function writeAxis(XMLWriter $objWriter, Chart\Axis $oAxis, string $ty
22972297
return;
22982298
}
22992299

2300+
$crossesAt = $oAxis->getCrossesAt();
2301+
23002302
if (Chart\Axis::AXIS_X == $typeAxis) {
23012303
$mainElement = 'c:catAx';
23022304
$axIdVal = '52743552';
2303-
$axPosVal = 'b';
2305+
$axPosVal = $crossesAt === 'max' ? 't' : 'b';
23042306
$crossAxVal = '52749440';
23052307
} else {
23062308
$mainElement = 'c:valAx';
23072309
$axIdVal = '52749440';
2308-
$axPosVal = 'l';
2310+
$axPosVal = $crossesAt === 'max' ? 'r' : 'l';
23092311
$crossAxVal = '52743552';
23102312
}
23112313

@@ -2485,10 +2487,16 @@ protected function writeAxis(XMLWriter $objWriter, Chart\Axis $oAxis, string $ty
24852487
$objWriter->writeAttribute('val', $crossAxVal);
24862488
$objWriter->endElement();
24872489

2488-
// c:crosses
2489-
$objWriter->startElement('c:crosses');
2490-
$objWriter->writeAttribute('val', 'autoZero');
2491-
$objWriter->endElement();
2490+
// c:crosses "autoZero" | "min" | "max" | custom string value
2491+
if (in_array($crossesAt, ['autoZero', 'min', 'max'])) {
2492+
$objWriter->startElement('c:crosses');
2493+
$objWriter->writeAttribute('val', $crossesAt);
2494+
$objWriter->endElement();
2495+
} else {
2496+
$objWriter->startElement('c:crossesAt');
2497+
$objWriter->writeAttribute('val', $crossesAt);
2498+
$objWriter->endElement();
2499+
}
24922500

24932501
if (Chart\Axis::AXIS_X == $typeAxis) {
24942502
// c:lblAlgn

tests/PhpPresentation/Tests/Shape/Chart/AxisTest.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ public function testBounds(): void
6161
$this->assertNull($object->getMaxBounds());
6262
}
6363

64+
public function testCrossesAt(): void
65+
{
66+
$object = new Axis();
67+
68+
$this->assertEquals(Axis::CROSSES_AUTO, $object->getCrossesAt());
69+
$this->assertInstanceOf(Axis::class, $object->setCrossesAt(Axis::CROSSES_MAX));
70+
$this->assertEquals(Axis::CROSSES_MAX, $object->getCrossesAt());
71+
}
72+
6473
public function testFont(): void
6574
{
6675
$object = new Axis();

tests/PhpPresentation/Tests/Writer/PowerPoint2007/PptChartsTest.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,54 @@ public function testAxisBounds(): void
276276
$this->assertIsSchemaECMA376Valid();
277277
}
278278

279+
public function testAxisCrosses(): void
280+
{
281+
$oSeries = new Series('Downloads', $this->seriesData);
282+
$oSeries->getFill()->setStartColor(new Color('FFAABBCC'));
283+
$oLine = new Line();
284+
$oLine->addSeries($oSeries);
285+
$oShape = $this->oPresentation->getActiveSlide()->createChartShape();
286+
$oShape->getPlotArea()->setType($oLine);
287+
288+
$elementCrosses = '/c:chartSpace/c:chart/c:plotArea/c:catAx/c:crosses';
289+
$elementCrossesAt = '/c:chartSpace/c:chart/c:plotArea/c:catAx/c:crossesAt';
290+
$elementAxPos = '/c:chartSpace/c:chart/c:plotArea/c:catAx/c:axPos';
291+
292+
// Default autoZero
293+
$this->assertZipXmlElementExists('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrosses);
294+
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrosses, 'val', 'autoZero');
295+
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementAxPos, 'val', 'b');
296+
$this->assertIsSchemaECMA376Valid();
297+
298+
// Crosses max
299+
$oShape->getPlotArea()->getAxisX()->setCrossesAt(Axis::CROSSES_MAX);
300+
$this->resetPresentationFile();
301+
302+
$this->assertZipXmlElementExists('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrosses);
303+
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrosses, 'val', 'max');
304+
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementAxPos, 'val', 't');
305+
$this->assertIsSchemaECMA376Valid();
306+
307+
// Crosses min
308+
$oShape->getPlotArea()->getAxisX()->setCrossesAt(Axis::CROSSES_MIN);
309+
$this->resetPresentationFile();
310+
311+
$this->assertZipXmlElementExists('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrosses);
312+
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrosses, 'val', 'min');
313+
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementAxPos, 'val', 'b');
314+
$this->assertIsSchemaECMA376Valid();
315+
316+
// Crosses custom value
317+
$oShape->getPlotArea()->getAxisX()->setCrossesAt('10');
318+
$this->resetPresentationFile();
319+
320+
$this->assertZipXmlElementNotExists('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrosses);
321+
$this->assertZipXmlElementExists('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrossesAt);
322+
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementCrossesAt, 'val', '10');
323+
$this->assertZipXmlAttributeEquals('ppt/charts/' . $oShape->getIndexedFilename(), $elementAxPos, 'val', 'b');
324+
$this->assertIsSchemaECMA376Valid();
325+
}
326+
279327
public function testAxisFont(): void
280328
{
281329
$oSlide = $this->oPresentation->getActiveSlide();

0 commit comments

Comments
 (0)