gauge.gno
2.82 Kb · 115 lines
1// Package gauge provides a simple way to render a gauge bar in SVG format.
2package gauge
3
4import (
5 "gno.land/p/demo/svg"
6 "gno.land/p/nt/ufmt"
7)
8
9type Config struct {
10 PercentOnly bool
11 Width int
12 CanvasHeight int
13 FontSize int
14 PaddingH int
15}
16
17var DefaultConfig = Config{
18 PercentOnly: false,
19 Width: 300,
20 CanvasHeight: 30,
21 FontSize: 16,
22 PaddingH: 6,
23}
24
25// Render generates an SVG gauge bar.
26// Parameters:
27// - value: current value (must be <= total)
28// - total: maximum value (must be > 0)
29// - label: text label to display on the left side of the gauge
30// - color: color of the filled part of the gauge (e.g., "#4caf50")
31// - config: configuration options:
32// - PercentOnly: Only display the percentage on the right side; otherwise, display "value / total · percentage"
33// - Width: Width of the gauge in pixels
34// - CanvasHeight: Height of the gauge in pixels
35// - FontSize: Font size of the text in pixels
36// - PaddingH: Horizontal padding (for the text) in pixels
37//
38// Example usage: gauge.Render(30, 100, "Progress", "#4caf50", &gauge.Config{PercentOnly: true, Width: 400})
39func Render(value int, total int, label string, color string, config Config) string {
40 if total <= 0 {
41 return "jauge fails: total must be greater than 0"
42 }
43 if value <= 0 {
44 return "jauge fails: value must be greater than 0"
45 }
46 if value > total {
47 return "jauge fails: value cannot be greater than total"
48 }
49
50 canvasWidth := config.Width
51 canvasHeight := config.CanvasHeight
52 fontSize := config.FontSize
53 paddingH := config.PaddingH
54 canvas := svg.NewCanvas(canvasWidth, canvasHeight)
55
56 ratio := 0.0
57 if total > 0 {
58 ratio = float64(value) / float64(total)
59 }
60
61 leftText := label
62 rightText := ufmt.Sprintf("%d / %d · %0.0f%%", value, total, ratio*100)
63 if config.PercentOnly {
64 rightText = ufmt.Sprintf("%0.0f%%", ratio*100)
65 }
66
67 // Background
68 canvas.Append(svg.Rectangle{
69 X: 0,
70 Y: 0,
71 Width: canvasWidth,
72 Height: canvasHeight,
73 Fill: "#e0e0e0",
74 RX: 2,
75 RY: 2,
76 })
77 // Filled bar
78 canvas.Append(svg.Rectangle{
79 X: 0,
80 Y: 0,
81 Width: int(ratio * float64(canvasWidth)),
82 Height: canvasHeight,
83 Fill: color,
84 RX: 2,
85 RY: 2,
86 })
87 // Left text (label)
88 canvas.Append(svg.Text{
89 X: paddingH,
90 Y: canvasHeight / 2,
91 Text: leftText,
92 Fill: "#000000",
93 Attr: svg.BaseAttrs{
94 Style: ufmt.Sprintf(
95 "font-family:'Inter var',sans-serif;font-size:%dpx;dominant-baseline:middle;text-anchor:start;",
96 fontSize,
97 ),
98 },
99 })
100 // Right text (ratio + %)
101 canvas.Append(svg.Text{
102 X: canvasWidth - paddingH,
103 Y: canvasHeight / 2,
104 Text: rightText,
105 Fill: "#000000",
106 Attr: svg.BaseAttrs{
107 Style: ufmt.Sprintf(
108 "font-family:'Inter var',sans-serif;font-size:%dpx;dominant-baseline:middle;text-anchor:end;",
109 fontSize,
110 ),
111 },
112 })
113
114 return canvas.Render("Jauge")
115}