Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
typescript
coloration
Commits
54eb255a
Commit
54eb255a
authored
Jan 20, 2019
by
Zéfling
🎨
Browse files
Make it possible to change color by parameters
- Update interface to test this. - Best support of HSL/HSV
parent
c1263c22
Changes
4
Hide whitespace changes
Inline
Side-by-side
projects/coloration/src/lib/coloration.ts
View file @
54eb255a
...
...
@@ -7,8 +7,19 @@ const pattern = {
hsva
:
/^hsla
?\(([\d]
*
(\.[\d]
+
)?)(
,
?\s
*|
\s
+
)([\d]
*
(\.[\d]
+
)?)\%(
,
?\s
*|
\s
+
)([\d]
*
(\.[\d]
+
)?)\%((
,
\s
*
)([\d]
*
(\.[\d]
+
)?))?\)
$/i
};
export
interface
RGB
{
r
:
number
;
g
:
number
;
b
:
number
;
}
export
interface
HSV
{
h
:
number
;
s
:
number
;
v
:
number
;
}
export
interface
ColorData
{
r
?:
number
;
g
?:
number
;
b
?:
number
;
h
?:
number
;
s
?:
number
;
v
?:
number
;
color
?:
string
;
luminosity
?:
number
;
}
export
class
Coloration
{
/**
* CSS color list
*/
static
colorsName
:
any
=
{
// CSS 1
black
:
'
#000000
'
,
silver
:
'
#c0c0c0
'
,
gray
:
'
#808080
'
,
white
:
'
#ffffff
'
,
maroon
:
'
#800000
'
,
red
:
'
#ff0000
'
,
...
...
@@ -51,48 +62,121 @@ export class Coloration {
};
private
intColor
:
number
;
private
rgb
:
RGB
=
{
r
:
0
,
g
:
0
,
b
:
0
};
private
hsv
:
HSV
=
{
h
:
0
,
s
:
0
,
v
:
0
};
constructor
(
public
color
:
string
)
{
this
.
intColor
=
this
.
parseColor
(
color
);
}
/**
* HEX color
*/
getColor
()
{
return
this
.
intRbgToString
(
this
.
intColor
);
this
.
updateColor
();
}
/**
* change the luminosity of a color
* @param lum value between -1 and 1
*/
changeLuminosity
(
lum
:
number
):
string
{
lum
=
Math
.
min
(
Math
.
max
(
lum
||
0
,
-
1
),
1
);
return
this
.
maskColor
(
lum
<
0
?
'
#000
'
:
'
#FFF
'
,
Math
.
abs
(
lum
));
changeLuminosity
(
lum
:
number
):
Coloration
{
lum
=
this
.
minmax
(
lum
,
-
1
,
1
);
this
.
maskColor
(
lum
<
0
?
'
#000
'
:
'
#FFF
'
,
Math
.
abs
(
lum
));
return
this
;
}
/**
* add color with a mark
* @param color additional color
* @param opacity value of opacity between 0 and 1 for the additional color
* @returns hexa color
*/
maskColor
(
color
:
string
,
opacity
:
number
=
1
):
string
{
maskColor
(
color
:
string
,
opacity
:
number
=
1
):
Coloration
{
const
baseColor
=
this
.
parseColor
(
this
.
c
olor
)
;
const
baseColor
=
this
.
intC
olor
;
const
additionalColor
=
this
.
parseColor
(
color
);
const
lum
=
Math
.
min
(
Math
.
max
(
opacity
||
0
,
0
)
,
1
);
const
lum
=
this
.
min
max
(
opacity
,
0
,
1
);
const
R
=
baseColor
>>
16
;
const
G
=
baseColor
>>
8
&
0x00FF
;
const
B
=
baseColor
&
0x0000FF
;
return
this
.
intRbgToString
(
this
.
rgbToInt
(
this
.
intColor
=
this
.
rgbToInt
(
Math
.
round
(((
additionalColor
>>
16
)
-
R
)
*
lum
)
+
R
,
Math
.
round
(((
additionalColor
>>
8
&
0x00FF
)
-
G
)
*
lum
)
+
G
,
Math
.
round
(((
additionalColor
&
0x0000FF
)
-
B
)
*
lum
)
+
B
));
);
this
.
updateColor
();
return
this
;
}
/**
* change color with color parameters
* @param colorData additionnal parameters
*/
addColor
(
colorData
:
ColorData
)
{
if
(
colorData
.
luminosity
)
{
this
.
changeLuminosity
(
colorData
.
luminosity
);
}
if
(
colorData
.
r
||
colorData
.
g
||
colorData
.
b
)
{
if
(
colorData
.
r
)
{
console
.
log
(
this
.
rgb
.
r
,
colorData
.
r
,
this
.
rgb
.
r
+
colorData
.
r
);
this
.
rgb
.
r
=
this
.
minmax
(
this
.
rgb
.
r
+
(
+
colorData
.
r
),
0
,
255
);
console
.
log
(
this
.
rgb
.
r
);
}
if
(
colorData
.
g
)
{
this
.
rgb
.
g
=
this
.
minmax
(
this
.
rgb
.
g
+
(
+
colorData
.
g
),
0
,
255
);
}
if
(
colorData
.
b
)
{
this
.
rgb
.
r
=
this
.
minmax
(
this
.
rgb
.
b
+
(
+
colorData
.
b
),
0
,
255
);
}
this
.
intColor
=
this
.
rgbToInt
(
this
.
rgb
.
r
,
this
.
rgb
.
g
,
this
.
rgb
.
b
);
this
.
updateColor
();
}
if
(
colorData
.
h
||
colorData
.
s
||
colorData
.
v
)
{
if
(
colorData
.
r
)
{
this
.
hsv
.
h
=
(
this
.
hsv
.
h
+
(
+
colorData
.
h
)
+
360
)
%
360
;
}
if
(
colorData
.
s
)
{
this
.
hsv
.
s
=
this
.
minmax
(
this
.
hsv
.
s
+
(
+
colorData
.
s
),
0
,
100
);
}
if
(
colorData
.
v
)
{
this
.
hsv
.
v
=
this
.
minmax
(
this
.
hsv
.
v
+
(
+
colorData
.
v
),
0
,
100
);
}
this
.
intColor
=
this
.
hsvToInt
(
this
.
hsv
.
h
,
this
.
hsv
.
s
,
this
.
hsv
.
v
);
this
.
updateColor
();
}
return
this
;
}
/**
* color in #HEX format
*/
toHEX
():
string
{
return
'
#
'
+
(
0x1000000
+
this
.
intColor
).
toString
(
16
).
slice
(
1
);
}
/**
* color in HVL() format
*/
toHSL
():
string
{
return
`hsl(
${
this
.
hsv
.
h
}
,
${
this
.
hsv
.
s
}
%,
${
this
.
hsv
.
v
}
%)`
;
}
/**
* color in RGB() format
*/
toRGB
():
string
{
return
`rgb(
${
this
.
rgb
.
r
}
,
${
this
.
rgb
.
g
}
,
${
this
.
rgb
.
b
}
)`
;
}
private
updateColor
()
{
// update RGB
this
.
rgb
.
r
=
this
.
intColor
>>
16
;
this
.
rgb
.
g
=
this
.
intColor
>>
8
&
0x00FF
;
this
.
rgb
.
b
=
this
.
intColor
&
0x0000FF
;
// update HSL
this
.
hsv
=
this
.
rgb2hsv
(
this
.
rgb
.
r
,
this
.
rgb
.
g
,
this
.
rgb
.
b
);
}
/**
...
...
@@ -130,7 +214,7 @@ export class Coloration {
// validate hsv() / hsva()
const
matchHsv
=
String
(
color
).
match
(
pattern
.
hsva
);
if
(
matchHsv
)
{
intColor
=
this
.
hsv
(
parseInt
(
matchHsv
[
1
],
10
),
parseInt
(
matchHsv
[
4
],
10
),
parseInt
(
matchHsv
[
7
],
10
));
intColor
=
this
.
hsv
ToInt
(
parseInt
(
matchHsv
[
1
],
10
),
parseInt
(
matchHsv
[
4
],
10
),
parseInt
(
matchHsv
[
7
],
10
));
}
}
...
...
@@ -146,7 +230,7 @@ export class Coloration {
* @returns int RGB
* @see https://stackoverflow.com/questions/2353211/hsl-to-rgb-color-conversion
*/
private
hsv
(
hue
:
number
,
saturation
:
number
,
value
:
number
):
number
{
private
hsv
ToInt
(
hue
:
number
,
saturation
:
number
,
value
:
number
):
number
{
saturation
=
Math
.
max
(
0
,
saturation
);
const
s
=
saturation
/
100
;
...
...
@@ -174,12 +258,64 @@ export class Coloration {
return
p
;
}
/**
* Convert RGB to HSV
* @param r [0, 255]
* @param g [0, 255]
* @param b [0, 255]
* @see https://stackoverflow.com/questions/39118528/rgb-to-hsl-conversion
* @see https://en.wikipedia.org/wiki/HSL_and_HSV#Formal_derivation
*/
private
rgb2hsv
(
r
:
number
,
g
:
number
,
b
:
number
):
HSV
{
// convert r,g,b [0,255] range to [0,1]
r
=
r
/
255
;
g
=
g
/
255
;
b
=
b
/
255
;
// get the min and max of r,g,b
const
max
=
Math
.
max
(
r
,
g
,
b
);
const
min
=
Math
.
min
(
r
,
g
,
b
);
// lightness is the average of the largest and smallest color components
const
val
=
(
max
+
min
)
/
2
;
let
hue
:
number
;
let
sat
:
number
;
if
(
max
===
min
)
{
// no saturation
hue
=
0
;
sat
=
0
;
}
else
{
const
c
=
max
-
min
;
// chroma
// saturation is simply the chroma scaled to fill
// the interval [0, 1] for every combination of hue and lightness
sat
=
c
/
(
1
-
Math
.
abs
(
2
*
val
-
1
));
switch
(
max
)
{
case
r
:
hue
=
(
g
-
b
)
/
c
+
(
g
<
b
?
6
:
0
);
break
;
case
g
:
hue
=
(
b
-
r
)
/
c
+
2
;
break
;
case
b
:
hue
=
(
r
-
g
)
/
c
+
4
;
break
;
}
}
return
{
h
:
Math
.
round
(
hue
*
60
),
// °
s
:
Math
.
round
(
sat
*
100
),
// %
v
:
Math
.
round
(
val
*
100
)
// %
};
}
private
rgbToInt
(
r
:
number
,
g
:
number
,
b
:
number
):
number
{
return
r
*
0x10000
+
g
*
0x100
+
b
;
}
private
in
tRbgToString
(
int
:
number
)
{
return
'
#
'
+
(
0x1000000
+
int
).
toString
(
16
).
slice
(
1
);
private
m
in
max
(
value
:
number
,
min
:
number
,
max
:
number
,
defaultValue
=
0
)
{
return
Math
.
min
(
Math
.
max
(
value
||
defaultValue
,
min
),
max
);
}
}
src/app/app.component.html
View file @
54eb255a
<!--The content below is only a placeholder and can be replaced.-->
<div>
<h1>
Welcome to {{ title }}!
</h1>
</div>
<h1>
{{ title }}
</h1>
<h2>
Test to change color:
</h2>
<div>
Color :
<input
type=
"color"
[value]=
"color"
(change)=
"changeColor($event)"
>
<main>
<form>
<fieldset>
<legend>
Base
</legend>
<label>
Color :
<input
type=
"text"
[(value)]=
"baseColor"
(change)=
"baseColor = $event.target.value"
></label>
<div
[style.background-color]=
"baseColor"
>
</div>
Luminosity :
<input
type=
"number"
max=
"1"
min=
"-1"
step=
"0.01"
[value]=
"luminosity"
(keyup)=
"changeLuminosity($event)"
(change)=
"changeLuminosity($event)"
>
</div>
<hr>
<div>
Color : {{color}}
</div>
<div>
ColorFinal : {{colorFinal}}
</div>
<div
[style.background-color]=
"colorFinal"
>
</div>
<hr>
<div>
ColorRgb : {{colorRgb}} -> {{colorRgbHex}}
</div>
<div
[style.background-color]=
"colorRgb"
>
</div>
<div
[style.background-color]=
"colorRgbHex"
>
</div>
<hr>
<div>
ColorHsv : {{colorHsv}} -> {{colorHsvHex}}
</div>
<div
[style.background-color]=
"colorHsv"
>
</div>
<div
[style.background-color]=
"colorHsvHex"
>
</div>
\ No newline at end of file
</fieldset>
<fieldset>
<legend>
Additionnal
</legend>
<div
class=
"additionnal"
>
<div
class=
"luminosity"
>
<label>
<span>
Luminosity:
</span><input
type=
"number"
min=
"-1.00"
max=
"1.00"
step=
"0.01"
[value]=
"luminosity"
(change)=
"luminosity = $event.target.value"
></label>
</div>
<div
class=
"red"
>
<label><span>
Red:
</span><input
type=
"number"
min=
"-255"
max=
"256"
step=
"1"
[value]=
"red"
(change)=
"red = $event.target.value"
></label>
</div>
<div
class=
"green"
>
<label><span>
Green:
</span><input
type=
"number"
min=
"-255"
max=
"256"
step=
"1"
[value]=
"green"
(change)=
"green = $event.target.value"
></label>
</div>
<div
class=
"blue"
>
<label><span>
Blue:
</span><input
type=
"number"
min=
"-255"
max=
"256"
step=
"1"
[value]=
"blue"
(change)=
"blue = $event.target.value"
></label>
</div>
<div
class=
"hue"
>
<label><span>
Hue (°):
</span><input
type=
"number"
max=
"-360"
max=
"360"
step=
"1"
[value]=
"hue"
(change)=
"hue = $event.target.value"
></label>
</div>
<div
class=
"saturation"
>
<label><span>
Saluration (%):
</span><input
type=
"number"
min=
"-255"
max=
"256"
step=
"1"
[value]=
"saturation"
(change)=
"saturation = $event.target.value"
></label>
</div>
<div
class=
"value"
>
<label><span>
Value (%):
</span><input
type=
"number"
min=
"-100"
max=
"100"
step=
"1"
[value]=
"value"
(change)=
"value = $event.target.value"
></label>
</div>
</div>
<div>
<button
type=
"button"
(click)=
"change()"
>
Change
</button>
</div>
</fieldset>
</form>
<aside>
<div>
HEX : {{colorHex}}
<div
[style.background-color]=
"colorHex"
>
</div>
</div>
<div>
RGB : {{colorRgb}}
<div
[style.background-color]=
"colorRgb"
>
</div>
</div>
<div>
HSL : {{colorHsl}}
<div
[style.background-color]=
"colorHsl"
>
</div>
</div>
</aside>
</main>
\ No newline at end of file
src/app/app.component.scss
View file @
54eb255a
main
{
display
:
flex
;
}
form
{
flex
:
2
;
}
aside
{
flex
:
1
;
padding
:
0
15px
}
.additionnal
{
display
:
grid
;
width
:
100%
;
grid-template
:
"lum . . "
35px
"red green blue "
35px
"hue sat value"
35px
/
1fr
1fr
1fr
;
label
{
display
:flex
;
padding
:
0
15px
;
align-items
:
center
;
}
span
{
flex
:
1
;
}
}
.luminosity
{
grid-area
:
lum
;
}
.red
{
grid-area
:
red
;}
.green
{
grid-area
:
green
;}
.blue
{
grid-area
:
blue
;}
.hue
{
grid-area
:
hue
;}
.saturation
{
grid-area
:
sat
;}
.value
{
grid-area
:
value
;}
\ No newline at end of file
src/app/app.component.ts
View file @
54eb255a
...
...
@@ -9,40 +9,40 @@ import { Coloration } from 'projects/coloration/src/public_api';
export
class
AppComponent
{
title
=
'
coloration-demo
'
;
color
=
'
#FF0000
'
;
colorRgb
=
'
rgb(50, 75, 255)
'
;
colorRgbHex
:
string
;
colorHsv
=
'
hsl(300, 50%, 70%)
'
;
colorHsvHex
:
string
;
baseColor
=
''
;
luminosity
=
0
;
luminosity
=
0.00
;
red
=
0
;
green
=
0
;
blue
=
0
;
hue
=
0
;
saturation
=
0
;
value
=
0
;
colorFinal
:
string
;
colorHex
:
string
;
colorRgb
:
string
;
colorHsl
:
string
;
constructor
()
{
this
.
calculColor
();
const
colorRgb
=
new
Coloration
(
this
.
colorRgb
);
this
.
colorRgbHex
=
colorRgb
.
getColor
();
const
colorHsv
=
new
Coloration
(
this
.
colorHsv
);
this
.
colorHsvHex
=
colorHsv
.
getColor
();
}
changeColor
(
event
:
Event
)
{
this
.
color
=
(
event
.
target
as
any
).
value
;
this
.
calculColor
();
}
changeLuminosity
(
event
:
Event
)
{
this
.
luminosity
=
parseFloat
((
event
.
target
as
any
).
value
);
this
.
calculColor
();
}
calculColor
()
{
const
color
=
new
Coloration
(
this
.
color
);
this
.
colorFinal
=
color
.
changeLuminosity
(
this
.
luminosity
);
change
()
{
const
color
=
new
Coloration
(
this
.
baseColor
);
color
.
addColor
({
r
:
this
.
red
,
g
:
this
.
green
,
b
:
this
.
blue
,
h
:
this
.
hue
,
s
:
this
.
saturation
,
v
:
this
.
value
,
luminosity
:
this
.
luminosity
});
console
.
log
(
color
);
this
.
colorHex
=
color
.
toHEX
();
this
.
colorHsl
=
color
.
toHSL
();
this
.
colorRgb
=
color
.
toRGB
();
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment