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