xref: /webtrees/app/ColorGenerator.php (revision d11be7027e34e3121be11cc025421873364403f9)
1<?php
2
3/**
4 * webtrees: online genealogy
5 * Copyright (C) 2023 webtrees development team
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18declare(strict_types=1);
19
20namespace Fisharebest\Webtrees;
21
22/**
23 * Generate a range of colurs for the lifespan chart.
24 */
25class ColorGenerator
26{
27    private int $hue;
28
29    private int $basehue;
30
31    private int $saturation;
32
33    private int $lightness;
34
35    private int $baselightness;
36
37    private float $alpha;
38
39    private int $range;
40
41    /**
42     * Create a color generator.
43     *
44     * @param int   $hue        0Deg = Red, 120Deg = green, 240Deg = blue)
45     * @param int   $saturation
46     * @param int   $lightness
47     * @param float $alpha
48     * @param int   $range      sign determines direction. positive = clockwise, negative = anticlockwise
49     */
50    public function __construct(int $hue, int $saturation, int $lightness, float $alpha, int $range)
51    {
52        $this->hue           = $hue;
53        $this->basehue       = $hue;
54        $this->saturation    = $saturation;
55        $this->lightness     = $lightness;
56        $this->baselightness = $lightness;
57        $this->alpha         = $alpha;
58        $this->range         = $range;
59    }
60
61    /**
62     * Function getNextColor
63     *
64     * $lightness cycles between $baselightness and 100% in $lightnessStep steps
65     * $hue cycles on each complete $lightness cycle
66     * between $basehue and $basehue + $range degrees in $hueStep degrees
67     *
68     * @param int $lightnessStep
69     * @param int $hueStep
70     *
71     * @return string
72     */
73    public function getNextColor(int $lightnessStep = 10, int $hueStep = 15): string
74    {
75        $lightness = $this->lightness + $lightnessStep;
76        $hue       = $this->hue;
77
78        if ($lightness >= 100) {
79            $lightness = $this->baselightness;
80            if ($this->range > 0) {
81                $hue += $hueStep;
82            } else {
83                $hue -= $hueStep;
84            }
85            if (($hue - $this->basehue) * ($hue - ($this->basehue + $this->range)) >= 0) {
86                $hue = $this->basehue;
87            }
88            $this->hue = $hue;
89        }
90        $this->lightness = $lightness;
91
92        return sprintf('hsla(%d, %d%%, %d%%, %0.2f)', $this->hue, $this->saturation, $this->lightness, $this->alpha);
93    }
94}
95