xref: /webtrees/app/ColorGenerator.php (revision 24f2a3af38709f9bf0a739b30264240d20ba34e8)
1<?php
2
3/**
4 * webtrees: online genealogy
5 * Copyright (C) 2021 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    /** @var int Current hue */
28    private $hue;
29
30    /** @var int Initial hue */
31    private $basehue;
32
33    /** @var int Saturation */
34    private $saturation;
35
36    /** @var int Lightness */
37    private $lightness;
38
39    /** @var int Initial lightness */
40    private $baselightness;
41
42    /** @var float Alpha transparancy */
43    private $alpha;
44
45    /** @var int Clockwise or anticlockwise color wheel */
46    private $range;
47
48    /**
49     * Create a color generator.
50     *
51     * @param int   $hue        0Deg = Red, 120Deg = green, 240Deg = blue)
52     * @param int   $saturation
53     * @param int   $lightness
54     * @param float $alpha
55     * @param int   $range      sign determines direction. positive = clockwise, negative = anticlockwise
56     */
57    public function __construct(int $hue, int $saturation, int $lightness, float $alpha, int $range)
58    {
59        $this->hue           = $hue;
60        $this->basehue       = $hue;
61        $this->saturation    = $saturation;
62        $this->lightness     = $lightness;
63        $this->baselightness = $lightness;
64        $this->alpha         = $alpha;
65        $this->range         = $range;
66    }
67
68    /**
69     * Function getNextColor
70     *
71     * $lightness cycles between $baselightness and 100% in $lightnessStep steps
72     * $hue cycles on each complete $lightness cycle
73     * between $basehue and $basehue + $range degrees in $hueStep degrees
74     *
75     * @param int $lightnessStep
76     * @param int $hueStep
77     *
78     * @return string
79     */
80    public function getNextColor(int $lightnessStep = 10, int $hueStep = 15): string
81    {
82        $lightness = $this->lightness + $lightnessStep;
83        $hue       = $this->hue;
84
85        if ($lightness >= 100) {
86            $lightness = $this->baselightness;
87            if ($this->range > 0) {
88                $hue += $hueStep;
89            } else {
90                $hue -= $hueStep;
91            }
92            if (($hue - $this->basehue) * ($hue - ($this->basehue + $this->range)) >= 0) {
93                $hue = $this->basehue;
94            }
95            $this->hue = $hue;
96        }
97        $this->lightness = $lightness;
98
99        return sprintf('hsla(%d, %d%%, %d%%, %0.2f)', $this->hue, $this->saturation, $this->lightness, $this->alpha);
100    }
101}
102