Skip to content

Commit

Permalink
Add grouped bar chart (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
maantje authored Jan 22, 2025
1 parent 0b87455 commit 88ff247
Show file tree
Hide file tree
Showing 17 changed files with 557 additions and 25 deletions.
50 changes: 33 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,31 +23,47 @@ composer require maantje/charts

Below are some examples of the types of charts you can create using this library. Click on the links to view the source code for each example.

### Simple line chart
![alt text](./examples/output/simple-line-chart.svg)
[View source](./examples/simple-line-chart.php)

### Curved line chart
![alt text](./examples/output/simple-curved-chart.svg)
[View source](./examples/simple-curved-chart.php)
- [Simple Line Chart](#simple-line-chart)
- [Curved Line Chart](#curved-line-chart)
- [Step Line Chart](#step-line-chart)
- [Bar Chart](#bar-chart)
- [Stacked Bar Chart](#stacked-bar-chart)
- [Grouped Bar Chart](#grouped-bar-chart)
- [Advanced Line Chart](#advanced-line-chart)
- [Advanced Bar Chart](#advanced-bar-chart)
- [Mixed Chart](#mixed-chart)
- [Pie Chart](#pie-chart)


### Simple Line Chart
![alt text](./examples/output/line-chart.svg)
[View source](./examples/line-chart.php)

### Curved Line Chart
![alt text](./examples/output/curved-line-chart.svg)
[View source](./examples/curved-line-chart.php)

### Step line chart
![alt text](./examples/output/simple-step-chart.svg)
[View source](./examples/simple-step-chart.php)
![alt text](./examples/output/step-line-chart.svg)
[View source](./examples/step-line-chart.php)

### Bar Chart
![alt text](./examples/output/bar-chart.svg)
[View source](./examples/bar-chart.php)

### Simple bar chart
![alt text](./examples/output/simple-bar-chart.svg)
[View source](./examples/simple-bar-chart.php)
### Stacked Bar Chart
![alt text](./examples/output/stacked-bar-chart.svg)
[View source](./examples/stacked-bar-chart.php)

### Simple stacked chart
![alt text](./examples/output/simple-stacked-bar-chart.svg)
[View source](./examples/simple-stacked-bar-chart.php)
### Grouped Bar Chart
![alt text](./examples/output/grouped-bar-chart.svg)
[View source](./examples/grouped-bar-chart.php)

### Advanced line charts
### Advanced Line Chart
![alt text](./examples/output/advanced-line-chart.svg)
[View source](./examples/advanced-line-chart.php)

### Advanced bar chart
### Advanced Bar Chart
![alt text](./examples/output/advanced-bar-chart.svg)
[View source](./examples/advanced-bar-chart.php)

Expand Down
File renamed without changes.
File renamed without changes.
140 changes: 140 additions & 0 deletions examples/grouped-bar-chart.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
<?php

require '../vendor/autoload.php';

use Maantje\Charts\Bar\Bar;
use Maantje\Charts\Bar\BarGroup;
use Maantje\Charts\Bar\Bars;
use Maantje\Charts\Chart;
use Maantje\Charts\YAxis;

$chart = new Chart(
yAxis: new YAxis(
minValue: 0,
maxValue: 1000,
),
series: [
new Bars(
bars: [
new BarGroup(
name: 'January',
bars: [
new Bar(
value: 101,
color: '#1E90FF',
),
new Bar(
value: 251,
color: '#32CD32',
),
new Bar(
value: 389,
color: '#FFA500',
),
new Bar(
value: 457,
color: '#FFD700',
),
new Bar(
value: 601,
color: '#FF4500',
),
],
radius: 10,
),
new BarGroup(
name: 'February',
bars: [
new Bar(
value: 73,
color: '#1E90FF',
radius: 10,
),
new Bar(
value: 223,
color: '#32CD32',
radius: 10,
),
new Bar(
value: 347,
color: '#FFA500',
radius: 10,
),
new Bar(
value: 509,
color: '#FFD700',
radius: 10,
),
new Bar(
value: 653,
color: '#FF4500',
radius: 10,
),
],
),
new BarGroup(
name: 'March',
bars: [
new Bar(
value: 113,
color: '#1E90FF',
radius: 10,
),
new Bar(
value: 281,
color: '#32CD32',
radius: 10,
),
new Bar(
value: 401,
color: '#FFA500',
radius: 10,
),
new Bar(
value: 541,
color: '#FFD700',
radius: 10,
),
new Bar(
value: 733,
color: '#FF4500',
radius: 10,
),
],
),
new BarGroup(
name: 'April',
bars: [
new Bar(
value: 193,
color: '#1E90FF',
radius: 10,
),
new Bar(
value: 311,
color: '#32CD32',
radius: 10,
),
new Bar(
value: 457,
color: '#FFA500',
radius: 10,
),
new Bar(
value: 613,
color: '#FFD700',
radius: 10,
),
new Bar(
value: 809,
color: '#FF4500',
radius: 10,
),
],
),
],
),
],
);

echo $chart->render();
File renamed without changes.
File renamed without changes
File renamed without changes
37 changes: 37 additions & 0 deletions examples/output/grouped-bar-chart.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes.
File renamed without changes.
15 changes: 9 additions & 6 deletions src/Bar/Bar.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@
class Bar implements BarContract
{
public function __construct(
public string $name,
public float $value,
public ?string $name = null,
public float $value = 0,
public ?string $yAxis = null,
public string $color = '#3498db',
public ?float $width = 100,
public string $labelColor = '#333',
public int $labelMarginY = 30
public int $labelMarginY = 30,
public ?int $radius = null,
) {}

public function render(Chart $chart, float $x, float $maxBarWidth): string
Expand All @@ -37,17 +38,19 @@ public function render(Chart $chart, float $x, float $maxBarWidth): string
width: $width,
height: $chart->bottom() - $y,
fill: $this->color,
title: $this->value
rx: $this->radius ?? 0,
ry: $this->radius ?? 0,
title: $this->value,
),
new Text(
$this->name ? new Text(
content: $this->name,
x: $labelX,
y: $chart->bottom() + $this->labelMarginY,
fontFamily: $chart->fontFamily,
fontSize: $chart->fontSize,
fill: $this->labelColor,
textAnchor: 'middle'
),
) : null,
]);
}

Expand Down
102 changes: 102 additions & 0 deletions src/Bar/BarGroup.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php

namespace Maantje\Charts\Bar;

use Maantje\Charts\Chart;
use Maantje\Charts\SVG\Fragment;
use Maantje\Charts\SVG\Line;
use Maantje\Charts\SVG\Text;

class BarGroup implements BarContract
{
/**
* @param Bar[] $bars
*/
public function __construct(
private readonly string $name,
private readonly int $margin = 5,
private readonly int $width = 100,
private readonly array $bars = [],
public string $labelColor = '#333',
public int $labelMarginY = 30,
public ?int $fontSize = null,
public ?int $radius = null,
) {
if (is_null($this->radius)) {
return;
}

foreach ($this->bars as $bar) {
if (is_null($bar->radius)) {
$bar->radius = $this->radius;
}
}
}

public function maxValue(): float
{
if (count($this->bars) === 0) {
return 0;
}

return max(array_map(fn (BarContract $bar) => $bar->value(), $this->bars));
}

public function minValue(): float
{
if (count($this->bars) === 0) {
return 0;
}

return min(array_map(fn (BarContract $bar) => $bar->value(), $this->bars));
}

public function render(Chart $chart, float $x, float $maxGroupWidth): string
{
$numBars = count($this->bars);
$barWidth = 0;

if ($numBars > 0) {
$barWidth = min($maxGroupWidth, $this->width) / $numBars;
}

$labelX = $x + ($maxGroupWidth / 2);
$startX = $x;
$x += ($maxGroupWidth / 2) - (($barWidth + $this->margin) * $numBars / 2);

return new Fragment([
new Line(
x1: $startX,
y1: $chart->bottom(),
x2: $startX,
y2: $chart->bottom() + 10,
),
...array_map(function (BarContract $bar) use ($barWidth, &$x, $chart) {
$svg = $bar->render($chart, $x + $this->margin, $barWidth);
$x += $this->margin + $barWidth;

return $svg;
}, $this->bars),
new Line(
x1: $startX + $maxGroupWidth,
y1: $chart->bottom(),
x2: $startX + $maxGroupWidth,
y2: $chart->bottom() + 10,
),
new Text(
content: $this->name,
x: $labelX,
y: $chart->bottom() + $this->labelMarginY,
fontFamily: $chart->fontFamily,
fontSize: $this->fontSize ?? $chart->fontSize,
fill: $this->labelColor,
textAnchor: 'middle'
),
]);
}

public function value(): float
{
return $this->maxValue();
}
}
Loading

0 comments on commit 88ff247

Please sign in to comment.