Gradients
This commit is contained in:
@@ -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,
|
137
webcontroller/style_colors.go
Normal file
137
webcontroller/style_colors.go
Normal 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)
|
||||
}
|
@@ -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
|
||||
|
Reference in New Issue
Block a user