• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

atinc / ngx-tethys / d9ae709b-3c27-4b69-b125-b8b80b54f90b

pending completion
d9ae709b-3c27-4b69-b125-b8b80b54f90b

Pull #2757

circleci

mengshuicmq
fix: fix code review
Pull Request #2757: feat(color-picker): color-picker support disabled (#INFR-8645)

98 of 6315 branches covered (1.55%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

2392 of 13661 relevant lines covered (17.51%)

83.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.36
/src/color-picker/helpers/color.class.ts
1
import { ThyColorsTable } from './colors-table.class';
2
import { ThyRgba } from './rgba.class';
3

1✔
4
const hsv2hsl = function (hue: number, sat: number, val: number) {
×
5
    return [hue, (sat * val) / ((hue = (2 - sat) * val) < 1 ? hue : 2 - hue) || 0, hue / 2];
6
};
7

8
export default class ThyColor {
×
9
    hue = 0;
×
10
    saturation = 0;
×
11
    value = 0;
×
12
    alpha = 1;
×
13
    enableAlpha = false;
×
14
    format = 'hex';
×
15
    displayValue = '#000000'; // 最终展示的值
×
16
    rgba: ThyRgba = new ThyRgba(0, 0, 0, 1);
×
17

×
18
    constructor(color?: string | { h: number; s: number; v: number; alpha: number }) {
19
        if (color) {
20
            this.stringToColor(color);
21
        }
×
22
    }
×
23

24
    private stringToColor(color: string | { h: number; s: number; v: number; alpha: number }): this {
25
        if (typeof color === 'string') {
26
            const str = color.replace(/ /g, '').toLowerCase();
×
27
            /**
28
             * try to find color by name in table
29
             */
30
            let rgba: ThyRgba = ThyColorsTable[str] || null;
×
31

×
32
            /**
×
33
             * hex find
×
34
             */
×
35
            if (str[0] === '#') {
×
36
                let hex = str.substr(1);
37
                const length = hex.length;
×
38
                let hexArray: string[] = [];
×
39

40
                if (length === 3) {
×
41
                    hexArray = hex.split('').map(value => value + value);
×
42
                } else if (length === 6) {
×
43
                    hexArray = hex.match(/.{2}/g);
×
44
                } else if (length === 8) {
×
45
                    const alpha = hex.substr(-2);
46
                    hex = hex.substr(0, length - 2);
×
47
                    this.alpha = this.roundNumber(parseInt(alpha || 'FF', 16) / 255);
×
48
                    hexArray = hex.match(/.{2}/g);
49
                }
50

×
51
                if (hexArray.length === 3) {
×
52
                    rgba = new ThyRgba(parseInt(hexArray[0], 16), parseInt(hexArray[1], 16), parseInt(hexArray[2], 16), this.alpha);
×
53
                }
×
54
            }
×
55
            const OpenParenthesis = str.indexOf('(');
×
56
            const CloseParenthesis = str.indexOf(')');
57
            if (OpenParenthesis !== -1 && CloseParenthesis + 1 === str.length) {
×
58
                const colorTypeName = str.substr(0, OpenParenthesis);
59
                const params = str.substr(OpenParenthesis + 1, CloseParenthesis - (OpenParenthesis + 1)).split(',');
×
60
                switch (colorTypeName) {
×
61
                    case 'rgba':
62
                        this.alpha = parseFloat(params.pop());
×
63
                    case 'rgb':
64
                        rgba = new ThyRgba(parseInt(params[0], 10), parseInt(params[1], 10), parseInt(params[2], 10), this.alpha);
×
65
                        break;
×
66
                    case 'hsla':
67
                        this.alpha = parseFloat(params.pop());
68
                    case 'hsl':
69
                        rgba = this.hslaToRgba(parseInt(params[0], 10), parseInt(params[1], 10), parseInt(params[2], 10), this.alpha);
70
                        break;
71
                    // case 'cmyk':
72
                    //     const cmyk = new Cmyk(
73
                    //         parseInt(params[0], 10),
74
                    //         parseInt(params[1], 10),
75
                    //         parseInt(params[2], 10),
76
                    //         parseInt(params[3], 10)
77
                    //     );
×
78
                    //     rgba = this.cmykToRgba(cmyk);
×
79
                    //     break;
×
80
                }
×
81
            }
82
            if (rgba) {
83
                this.rgba = new ThyRgba(rgba.red, rgba.green, rgba.blue, rgba.alpha);
84
                const hsv = this.rgbTohsv(rgba.red, rgba.green, rgba.blue);
×
85
                this.updateColor(hsv.h, hsv.s, hsv.v, rgba.alpha, false);
86
            }
×
87
        } else {
88
            this.updateColor(color.h, color.s, color.v, color.alpha, true);
×
89
        }
×
90
        return this;
×
91
    }
92

×
93
    public setRgba(red: number = null, green: number = null, blue: number = null, alpha: number = 1): this {
×
94
        if (red != null) {
95
            this.rgba.red = red;
×
96
        }
×
97

98
        if (green != null) {
×
99
            this.rgba.green = green;
×
100
        }
×
101

102
        if (blue != null) {
×
103
            this.rgba.blue = blue;
×
104
        }
×
105

106
        if (alpha != null) {
107
            alpha = alpha > 1 ? 1 : alpha < 0 ? 0 : alpha;
×
108
            this.rgba.alpha = alpha;
×
109
        }
×
110

×
111
        const { h, s, v } = this.rgbTohsv(this.rgba.red, this.rgba.green, this.rgba.blue);
×
112
        this.updateColor(h, s, v, this.rgba.alpha, false);
×
113
        return this;
×
114
    }
×
115

×
116
    rgbTohsv(r: number, g: number, b: number) {
×
117
        const red = r / 255;
×
118
        const green = g / 255;
119
        const blue = b / 255;
×
120
        const Cmax = Math.max(red, green, blue);
×
121
        const Cmin = Math.min(red, green, blue);
122
        const delta = Cmax - Cmin;
×
123
        let hue = 0;
×
124
        let saturation: number = Cmax === 0 ? 0 : delta / Cmax;
125
        let brightness: number = Cmax;
×
126
        if (Cmax !== Cmin) {
×
127
            switch (Cmax) {
128
                case red:
×
129
                    hue = (green - blue) / delta + (green < blue ? 6 : 0);
130
                    break;
×
131
                case green:
132
                    hue = 2 + (blue - red) / delta;
133
                    break;
×
134
                case blue:
135
                    hue = 4 + (red - green) / delta;
136
                    break;
×
137
            }
×
138
            hue /= 6;
×
139
        }
×
140

×
141
        return { h: Math.round(hue * 360), s: Math.round(saturation * 100), v: Math.round(brightness * 100) };
×
142
    }
×
143

×
144
    public getRgba(): ThyRgba {
×
145
        return new ThyRgba(this.rgba.red, this.rgba.green, this.rgba.blue, this.rgba.alpha);
×
146
    }
×
147

×
148
    private hslaToRgba(h: number, s: number, l: number, a: number): ThyRgba {
×
149
        const hue = h / 360;
150
        const saturation = s / 100;
×
151
        const lightness = l / 100;
×
152
        const alpha = a;
×
153

×
154
        let red = lightness;
155
        let green = lightness;
156
        let blue = lightness;
×
157

×
158
        if (saturation !== 0) {
159
            const q = lightness < 0.5 ? lightness * (1 + saturation) : lightness + saturation - lightness * saturation;
×
160
            const p = 2 * lightness - q;
×
161

162
            red = this.hueToRgb(p, q, hue + 1 / 3);
×
163
            green = this.hueToRgb(p, q, hue);
×
164
            blue = this.hueToRgb(p, q, hue - 1 / 3);
165
        }
×
166

×
167
        red = red * 255;
168
        green = green * 255;
×
169
        blue = blue * 255;
×
170

171
        return new ThyRgba(red, green, blue, alpha);
×
172
    }
173

174
    private hueToRgb(p: number, q: number, t: number): number {
×
175
        if (t < 0) {
176
            t += 1;
×
177
        }
×
178
        if (t > 1) {
×
179
            t -= 1;
×
180
        }
×
181
        if (t < 1 / 6) {
×
182
            return p + (q - p) * 6 * t;
×
183
        }
184
        if (t < 1 / 2) {
×
185
            return q;
×
186
        }
×
187
        if (t < 2 / 3) {
188
            return p + (q - p) * (2 / 3 - t) * 6;
×
189
        }
×
190
        return p;
×
191
    }
×
192

193
    private roundNumber(n: number): number {
×
194
        return Math.round(n * 100) / 100;
195
    }
196

×
197
    updateColor(h: number, s: number, v: number, alpha: number, updateRgba: boolean, enableAlpha = true, format = 'hex') {
×
198
        this.hue = Math.max(0, Math.min(360, h));
×
199
        this.saturation = Math.max(0, Math.min(100, s));
×
200
        this.value = Math.max(0, Math.min(100, v));
×
201
        this.alpha = alpha;
×
202
        if (updateRgba) {
×
203
            this.rgba = this.hsvaToRgba(this.hue, Math.round(this.saturation), Math.round(this.value), this.alpha);
×
204
        }
×
205
        this.enableAlpha = enableAlpha;
×
206
        this.format = format;
×
207
        this.getFinalValue();
×
208
    }
209

210
    public toHexString(alpha: boolean = false): string {
×
211
        let hex = '#' + ((1 << 24) | (this.rgba.getRed() << 16) | (this.rgba.getGreen() << 8) | this.rgba.getBlue()).toString(16).substr(1);
×
212
        if (alpha && this.rgba.alpha !== 1) {
×
213
            hex += ((1 << 8) | Math.round(this.rgba.alpha * 255)).toString(16).substr(1);
×
214
        }
215
        return hex.toUpperCase();
×
216
    }
×
217

×
218
    hsvaToRgba(h: number, s: number, v: number, alpha: number) {
×
219
        let red = 1;
220
        let green = 0;
×
221
        let blue = 0;
×
222
        const saturation = Math.round(s) / 100;
×
223
        const brightness = Math.round(v) / 100;
×
224
        const hex = h / 60;
225
        const primary = Math.floor(hex);
×
226
        const secoundary = hex - primary;
×
227
        const a = (1 - saturation) * brightness;
×
228
        const b = (1 - saturation * secoundary) * brightness;
×
229
        const c = (1 - saturation * (1 - secoundary)) * brightness;
230

×
231
        switch (primary) {
×
232
            case 6:
×
233
            case 0:
×
234
                red = brightness;
235
                green = c;
×
236
                blue = a;
×
237
                break;
×
238
            case 1:
×
239
                red = b;
240
                green = brightness;
×
241
                blue = a;
×
242
                break;
×
243
            case 2:
×
244
                red = a;
245
                green = brightness;
246
                blue = c;
×
247
                break;
×
248
            case 3:
×
249
                red = a;
250
                green = b;
×
251
                blue = brightness;
×
252
                break;
×
253
            case 4:
254
                red = c;
×
255
                green = a;
×
256
                blue = brightness;
257
                break;
×
258
            case 5:
×
259
                red = brightness;
260
                green = a;
×
261
                blue = b;
262
                break;
263
        }
264

×
265
        red = red * 255;
266
        green = green * 255;
×
267
        blue = blue * 255;
×
268

×
269
        return new ThyRgba(Math.round(red), Math.round(green), Math.round(blue), alpha);
270
    }
×
271

×
272
    getFinalValue() {
273
        let { hue, saturation, value, alpha, format } = this;
×
274
        if (this.enableAlpha) {
×
275
            switch (format) {
276
                case 'hsl':
×
277
                    const hsl = hsv2hsl(hue, saturation / 100, value / 100);
278
                    this.displayValue = `hsla(${hue}, ${Math.round(hsl[1] * 100)}%, ${Math.round(hsl[2] * 100)}%, ${alpha})`;
279
                    break;
280
                case 'hsv':
281
                    this.displayValue = `hsva(${hue}, ${Math.round(saturation)}%, ${Math.round(value)}%, ${alpha})`;
282
                    break;
283
                case 'rgb':
284
                    this.displayValue = `rgba(${this.rgba.red}, ${this.rgba.green}, ${this.rgba.blue}, ${this.rgba.alpha})`;
285
                    break;
286
                default:
287
                    this.displayValue = this.toHexString(true);
288
            }
289
        } else {
290
            switch (format) {
291
                case 'hsl':
292
                    const hsl = hsv2hsl(hue, saturation / 100, value / 100);
293
                    this.displayValue = `hsl(${hue}, ${Math.round(hsl[1] * 100)}%, ${Math.round(hsl[2] * 100)}%)`;
294
                    break;
295
                case 'hsv':
296
                    this.displayValue = `hsv(${hue}, ${Math.round(saturation)}%, ${Math.round(value)}%)`;
297
                    break;
298
                case 'rgb':
299
                    this.displayValue = `rgb(${this.rgba.red}, ${this.rgba.green}, ${this.rgba.blue})`;
300
                    break;
301
                default:
302
                    this.displayValue = this.toHexString();
303
            }
304
        }
305
    }
306
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc