Gradients

This commit is contained in:
2022-03-13 15:42:32 +01:00
parent 493e1495ce
commit 5a5eaa6615
91 changed files with 270 additions and 185 deletions

View File

@@ -55,44 +55,57 @@ func userStyle(style string) (s pixeldrainStyleSheet) {
// Set default colors
var noColor = hsl{0, 0, 0}
var setDefault = func(color *hsl, def hsl) {
var setDefaultHSL = func(color *hsl, def hsl) {
if *color == noColor {
*color = def
}
}
setDefault(&s.Link, s.Highlight.Add(0, 0, -.05))
setDefault(&s.InputDisabled, s.Input.Add(0, -.2, -.2))
setDefault(&s.ScrollbarForeground, s.Input)
setDefault(&s.ScrollbarHover, s.ScrollbarForeground.Add(0, 0, .1))
setDefault(&s.Layer1Text, s.Text)
setDefault(&s.Chart1, s.Highlight)
setDefault(&s.Chart2, s.Chart1.Add(120, 0, 0))
setDefault(&s.Chart3, s.Chart2.Add(120, 0, 0))
var setDefaultColor = func(color *Color, def Color) {
if *color == nil {
*color = def
}
}
setDefaultHSL(&s.Link, s.Highlight.Add(0, 0, -.05))
setDefaultHSL(&s.InputDisabled, s.Input.Add(0, -.2, -.2))
setDefaultHSL(&s.ScrollbarForeground, s.Input)
setDefaultHSL(&s.ScrollbarHover, s.ScrollbarForeground.Add(0, 0, .1))
setDefaultHSL(&s.Layer1Text, s.Text)
setDefaultHSL(&s.Chart1, s.Highlight)
setDefaultHSL(&s.Chart2, s.Chart1.Add(120, 0, 0))
setDefaultHSL(&s.Chart3, s.Chart2.Add(120, 0, 0))
setDefaultColor(&s.HighlightBackground, Gradient{180, []Color{s.Highlight, s.Highlight.Add(0, 0, -0.03)}})
setDefaultColor(&s.Background, s.Layer1)
setDefaultColor(&s.BackgroundPattern, s.Layer1)
setDefaultColor(&s.ParallaxSlider, s.Layer1)
setDefaultColor(&s.Navigation, NoColor)
setDefaultColor(&s.Body, s.Layer2)
return s
}
type Colour interface {
CSS() string
}
type pixeldrainStyleSheet struct {
Text hsl
Link hsl // Based on Highlight if undefined
Input hsl // Buttons, text fields
InputText hsl
InputDisabled hsl
HighlightBackground Color
Highlight hsl // Links, highlighted buttons, list navigation
HighlightText hsl // Text on buttons
Danger hsl
ScrollbarForeground hsl // Based on Highlight if undefined
ScrollbarHover hsl // Based on ScrollbarForeground if undefined
Layer1 hsl // Deepest and darkest layer
Layer1Text hsl // Based on Text if undefined
Layer2 hsl
Layer3 hsl
Layer4 hsl // Highest and brightest layer
Background Color
BackgroundPattern Color
ParallaxSlider Color
Navigation Color
Body Color
Layer1 hsl // Deepest and darkest layer
Layer1Text hsl // Based on Text if undefined
Layer2 hsl
Layer3 hsl
Layer4 hsl // Highest and brightest layer
// Colors to use in graphs
Chart1 hsl
@@ -112,6 +125,7 @@ func (s pixeldrainStyleSheet) String() string {
--input_color_dark: %s;
--input_text_color: %s;
--input_disabled_color: %s;
--highlight_background: %s;
--highlight_color: %s;
--highlight_color_dark: %s;
--highlight_text_color: %s;
@@ -121,15 +135,20 @@ func (s pixeldrainStyleSheet) String() string {
--scrollbar_hover_color: %s;
--scrollbar_background_color: %s;
--layer_1_color: %s;
--layer_1_color_border: %s;
--layer_1_text_color: %s;
--layer_2_color: %s;
--layer_2_color_border: %s;
--layer_3_color: %s;
--layer_3_color_border: %s;
--layer_4_color: %s;
--layer_4_color_border: %s;
--background: %s;
--background_pattern_color: %s;
--parallax_slider_color: %s;
--navigation_background: %s;
--body_background: %s;
--layer_1_color: %s;
--layer_1_color_border: %s;
--layer_1_text_color: %s;
--layer_2_color: %s;
--layer_2_color_border: %s;
--layer_3_color: %s;
--layer_3_color_border: %s;
--layer_4_color: %s;
--layer_4_color_border: %s;
--chart_1_color: %s;
--chart_2_color: %s;
@@ -143,6 +162,7 @@ func (s pixeldrainStyleSheet) String() string {
s.Input.Add(0, 0, -.02).CSS(),
s.InputText.CSS(),
s.InputDisabled.CSS(),
s.HighlightBackground.CSS(),
s.Highlight.CSS(),
s.Highlight.Add(0, 0, -.02).CSS(),
s.HighlightText.CSS(),
@@ -151,6 +171,11 @@ func (s pixeldrainStyleSheet) String() string {
s.ScrollbarForeground.CSS(),
s.ScrollbarHover.CSS(),
s.Layer2.CSS(), // Scrollbar background
s.Background.CSS(),
s.BackgroundPattern.CSS(),
s.ParallaxSlider.CSS(),
s.Navigation.CSS(),
s.Body.CSS(),
s.Layer1.CSS(),
s.Layer1.Add(0, 0, .05).CSS(),
s.Layer1Text.CSS(),
@@ -167,7 +192,7 @@ func (s pixeldrainStyleSheet) String() string {
)
}
func (s pixeldrainStyleSheet) Background(tpl *template.Template) template.URL {
func (s pixeldrainStyleSheet) BackgroundTiles(tpl *template.Template) template.URL {
var (
now = time.Now()
month = now.Month()
@@ -190,111 +215,35 @@ func (s pixeldrainStyleSheet) Background(tpl *template.Template) template.URL {
file = fmt.Sprintf("checker%d", now.UnixNano()%18)
}
if s.Light {
file += "_light"
}
var buf = bytes.Buffer{}
if err := tpl.ExecuteTemplate(&buf, file+".png", nil); err != nil {
if err := tpl.ExecuteTemplate(&buf, file+"_transparent.png", nil); err != nil {
panic(err)
}
return template.URL(buf.String())
}
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
}
// Following are all the available styles
var defaultPixeldrainStyle = pixeldrainStyleSheet{
Text: hsl{0, 0, .8},
Input: hsl{266, .85, .38},
InputText: hsl{0, 0, 1},
HighlightBackground: NewGradient(150, hsl{150, .84, .39}, hsl{85, .85, .35}),
Highlight: hsl{117, .63, .46},
HighlightText: hsl{0, 0, 0},
Danger: hsl{357, .63, .46},
ScrollbarForeground: hsl{266, .85, .40},
ScrollbarHover: hsl{266, .85, .50},
Layer1: hsl{275, .8, .07},
Layer2: hsl{275, .75, .12},
Layer3: hsl{275, .7, .18},
Layer4: hsl{275, .65, .24},
Background: NewGradient(140, hsl{225, .9, .14}, hsl{274, .85, .16}, hsl{274, .85, .16}, hsl{310, .8, .12}),
BackgroundPattern: NoColor,
ParallaxSlider: hsl{275, .8, .1},
Navigation: RGBA{0, 0, 0, 0.1},
Body: NoColor,
Layer1: hsl{275, .8, .07},
Layer2: hsl{275, .75, .12},
Layer3: hsl{275, .7, .18},
Layer4: hsl{275, .65, .24},
Shadow: hsl{0, 0, 0},
}
@@ -472,11 +421,13 @@ var snowstormPixeldrainStyle = pixeldrainStyleSheet{
ScrollbarForeground: hsl{193, .43, .67},
ScrollbarHover: hsl{193, .43, .76},
Layer1: hsl{220, .17, .32}, // hsl(220, 17%, 32%)
Layer1Text: hsl{219, .28, .88},
Layer2: hsl{219, .28, .88}, // hsl(219, 28%, 88%)
Layer3: hsl{218, .27, .92}, // hsl(218, 27%, 92%)
Layer4: hsl{218, .27, .94}, // hsl(218, 27%, 94%)
ParallaxSlider: hsl{220, .17, .20}, // Layer 1 but darker
Layer1: hsl{220, .17, .32}, // hsl(220, 17%, 32%)
Layer1Text: hsl{219, .28, .88},
BackgroundPattern: hsl{219, .28, .88}, // hsl(219, 28%, 88%)
Layer2: hsl{219, .28, .88}, // hsl(219, 28%, 88%)
Layer3: hsl{218, .27, .92}, // hsl(218, 27%, 92%)
Layer4: hsl{218, .27, .94}, // hsl(218, 27%, 94%)
Shadow: hsl{0, .0, .50},
Light: true,

View File

@@ -0,0 +1,137 @@
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
}
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)
}

View File

@@ -49,7 +49,7 @@ type TemplateData struct {
func (td *TemplateData) setStyle(style pixeldrainStyleSheet) {
td.Style = style
td.UserStyle = template.CSS(style.String())
td.BackgroundPattern = style.Background(td.tpm.tpl)
td.BackgroundPattern = style.BackgroundTiles(td.tpm.tpl)
}
func (wc *WebController) newTemplateData(w http.ResponseWriter, r *http.Request) (t *TemplateData) {
@@ -191,6 +191,8 @@ func (tm *TemplateManager) ParseTemplates(silent bool) {
file = []byte("data:image/png;base64," + base64.StdEncoding.EncodeToString(file))
} else if strings.HasSuffix(path, ".gif") {
file = []byte("data:image/gif;base64," + base64.StdEncoding.EncodeToString(file))
} else if strings.HasSuffix(path, ".webp") {
file = []byte("data:image/webp;base64," + base64.StdEncoding.EncodeToString(file))
}
// Wrap the resources in a template definition