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