diff --git a/demos/index.php b/demos/index.php index 1844d00..217d2b6 100644 --- a/demos/index.php +++ b/demos/index.php @@ -6,6 +6,7 @@ use Atk4\Chart\BarChart; use Atk4\Chart\ChartBox; +use Atk4\Chart\LineChart; use Atk4\Chart\PieChart; use Atk4\Data\Model; use Atk4\Data\Persistence; @@ -18,7 +19,7 @@ $t = [ 1 => ['name' => 'January', 'sales' => 20000, 'purchases' => 10000], 2 => ['name' => 'February', 'sales' => 23000, 'purchases' => 12000], - 3 => ['name' => 'March', 'sales' => 16000, 'purchases' => 11000], + 3 => ['name' => 'March', 'sales' => 16000, 'purchases' => 25000], 4 => ['name' => 'April', 'sales' => 14000, 'purchases' => 13000], ]; @@ -30,17 +31,43 @@ $app = new App(['title' => 'Chart Demo']); $app->initLayout([Layout\Centered::class]); -// split in columns +// split in columns - basic charts $columns = Columns::addTo($app->layout); // lets put your chart into a box -$cb = ChartBox::addTo($columns->addColumn(8), ['label' => ['Demo Bar Chart', 'icon' => 'book']]); +$cb = ChartBox::addTo($columns->addColumn(8), ['label' => ['Bar Chart', 'icon' => 'book']]); $chart = BarChart::addTo($cb); $chart->setModel($m, ['name', 'sales', 'purchases', 'profit']); +$chart->withCurrency('$'); // tweak our chart to support currencies better + +$cb = ChartBox::addTo($columns->addColumn(8), ['label' => ['Bar Chart Horizontal', 'icon' => 'book']]); +$chart = BarChart::addTo($cb); +$chart->setHorizontal(); +$chart->setModel($m, ['name', 'sales', 'purchases', 'profit']); +$chart->withCurrency('$'); + +// split in columns - stacked charts +$columns = Columns::addTo($app->layout); + +$cb = ChartBox::addTo($columns->addColumn(8), ['label' => ['Bar Chart Stacked', 'icon' => 'book']]); +$chart = BarChart::addTo($cb); +$chart->setModel($m, ['name', 'sales', 'purchases', 'profit'], ['Stack 1', 'Stack 2', 'Stack 1']); // Stack 1 => sales + profit, Stack 2 => purchases $chart->withCurrency('$'); -// tweak our chart to support currencies better -$cb = ChartBox::addTo($columns->addColumn(8), ['label' => ['Demo Pie Chart', 'icon' => 'book']]); +$cb = ChartBox::addTo($columns->addColumn(8), ['label' => ['Bar Chart Stacked', 'icon' => 'book']]); +$chart = BarChart::addTo($cb); +$chart->setModel($m, ['name', 'sales', 'purchases', 'profit'], [1, 1, 1]); // 1 => sales + purchases + profit +$chart->withCurrency('$'); + +// split in columns - more charts +$columns = Columns::addTo($app->layout); + +$cb = ChartBox::addTo($columns->addColumn(8), ['label' => ['Pie Chart', 'icon' => 'book']]); $chart = PieChart::addTo($cb); +$chart->setModel($m, ['name', 'purchases']); +$chart->withCurrency('$'); + +$cb = ChartBox::addTo($columns->addColumn(8), ['label' => ['Line Chart', 'icon' => 'book']]); +$chart = LineChart::addTo($cb); $chart->setModel($m, ['name', 'profit']); $chart->withCurrency('$'); diff --git a/src/BarChart.php b/src/BarChart.php index e3550ff..dfc8063 100644 --- a/src/BarChart.php +++ b/src/BarChart.php @@ -7,4 +7,15 @@ class BarChart extends Chart { public $type = 'bar'; + + /** + * Set this chart to be horizontal. + */ + public function setHorizontal(): void + { + $this->type = 'horizontalBar'; + + // in chartjs 3.9.1 replace with + // $this->setOptions(['indexAxis' => 'y']); + } } diff --git a/src/Chart.php b/src/Chart.php index e295217..676069f 100644 --- a/src/Chart.php +++ b/src/Chart.php @@ -9,6 +9,10 @@ use Atk4\Ui\JsExpression; use Atk4\Ui\View; +/** + * ChartJS 2.7.x documentation https://www.chartjs.org/docs/2.7.3/ + * ChartJS 3.9.1 documentation https://www.chartjs.org/docs/3.9.1/. + */ class Chart extends View { /** @var string HTML element type */ @@ -28,6 +32,7 @@ class Chart extends View ['rgba(75, 192, 192, 0.2)', 'rgba(75, 192, 192, 1)'], ['rgba(153, 102, 255, 0.2)', 'rgba(153, 102, 255, 1)'], ['rgba(255, 159, 64, 0.2)', 'rgba(255, 159, 64, 1)'], + ['rgba(20, 20, 20, 0.2)', 'rgba(20, 20, 20, 1)'], ]; /** @var array Options for chart.js widget */ @@ -115,9 +120,18 @@ public function setOptions(array $options) * This component will automatically figure out name of the chart, * series titles based on column captions etc. * + * Example for bar chart with two side-by side bars per category, and one of them stacked: + * + * $chart->setModel( + * $model, + * ['month', 'turnover_month_shoes', 'turnover_month_shirts', 'turnover_month_trousers', 'turnover_month_total_last_year'], + * [1, 1, 1, 2] // 1 => shoes+shirts+trousers, 2 => total last year + * ); + * * @param array $columns + * @param array $stacks */ - public function setModel(Model $model, array $columns = []): void + public function setModel(Model $model, array $columns = [], array $stacks = []): void { if ($columns === []) { throw new Exception('Second argument must be specified to Chart::setModel()'); @@ -130,10 +144,11 @@ public function setModel(Model $model, array $columns = []): void if ($key === 0) { $titleColumn = $column; - continue; // skipping labels + continue; // skipping label column } $colors = array_shift($this->niceColors); + $stack = array_shift($stacks); $this->datasets[$column] = [ 'label' => $model->getField($column)->getCaption(), @@ -142,6 +157,14 @@ public function setModel(Model $model, array $columns = []): void 'borderWidth' => 1, 'data' => [], ]; + + if ($stack !== null) { + $this->datasets[$column]['stack'] = $stack; + } + } + + if ($stacks !== []) { + $this->setOptions(['scales' => ['yAxes' => [0 => ['stacked' => true]], 'xAxes' => [0 => ['stacked' => true]]]]); } // prepopulate data-sets diff --git a/src/LineChart.php b/src/LineChart.php new file mode 100644 index 0000000..e1b87a4 --- /dev/null +++ b/src/LineChart.php @@ -0,0 +1,10 @@ +