Files
fnx_web/webcontroller/style_colors.go

154 lines
2.5 KiB
Go
Raw Normal View History

2022-03-13 15:42:32 +01:00
package webcontroller
import (
"fmt"
)
type Color interface {
CSS() string
}
// Raw CSS
type CSS string
func (c CSS) CSS() string { return string(c) }
const NoColor = CSS("none")
// HSL color
type hsl struct {
Hue int
Saturation float64
Lightness float64
}
func (orig hsl) RGB() string {
var r, g, b, q, p float64
var h, s, l = float64(orig.Hue) / 360, orig.Saturation, orig.Lightness
if s == 0 {
r, g, b = l, l, l
} else {
var hue2rgb = func(p, q, t float64) float64 {
if t < 0 {
t++
}
if t > 1 {
t--
}
if t < 1.0/6.0 {
return p + (q-p)*6*t
} else if t < 1.0/2.0 {
return q
} else if t < 2.0/3.0 {
return p + (q-p)*(2.0/3.0-t)*6
}
return p
}
if l < 0.5 {
q = l * (1 + s)
} else {
q = l + s - l*s
}
p = 2*l - q
r = hue2rgb(p, q, h+1.0/3.0)
g = hue2rgb(p, q, h)
b = hue2rgb(p, q, h-1.0/3.0)
}
return fmt.Sprintf("%02x%02x%02x", int(r*255), int(g*255), int(b*255))
}
func (orig hsl) CSS() string {
return "#" + orig.RGB()
}
// Add returns a NEW HSL struct, it doesn't modify the current one
func (h hsl) Add(hue int, saturation float64, lightness float64) hsl {
var new = hsl{
h.Hue + hue,
h.Saturation + saturation,
h.Lightness + lightness,
}
// Hue bounds correction
if new.Hue < 0 {
new.Hue += 360
} else if new.Hue > 360 {
new.Hue -= 360
}
// Saturation bounds check
if new.Saturation < 0 {
new.Saturation = 0
} else if new.Saturation > 1 {
new.Saturation = 1
}
// Lightness bounds check
if new.Lightness < 0 {
new.Lightness = 0
} else if new.Lightness > 1 {
new.Lightness = 1
}
return new
}
2022-04-04 12:37:58 +02:00
func (h hsl) WithAlpha(alpha float64) HSLA {
return HSLA{h, alpha}
}
type HSLA struct {
hsl
Alpha float64
}
func (hsla HSLA) CSS() string {
return fmt.Sprintf(
"hsla(%d, %.2f%%, %.2f%%, %.2f)",
hsla.Hue, hsla.Saturation*100, hsla.Lightness*100, hsla.Alpha,
)
}
2022-03-13 15:42:32 +01:00
type RGB struct {
R uint8
G uint8
B uint8
}
func (rgb RGB) CSS() string {
return fmt.Sprintf("#%02x%02x%02x", rgb.R, rgb.G, rgb.B)
}
type RGBA struct {
R uint8
G uint8
B uint8
A float64
}
func (rgba RGBA) CSS() string {
return fmt.Sprintf("rgba(%d, %d, %d, %f)", rgba.R, rgba.G, rgba.B, rgba.A)
}
type Gradient struct {
Angle int
Colors []Color
}
func NewGradient(angle int, colors ...Color) Gradient {
return Gradient{angle, colors}
}
func (g Gradient) CSS() string {
var colors string
for i, color := range g.Colors {
if i != 0 {
colors += ", "
}
colors += color.CSS()
}
return fmt.Sprintf("linear-gradient(%ddeg, %s)", g.Angle, colors)
}