Files
kjol/go/cmd/examples/go-wasm-web/app/chart.go

82 lines
2.5 KiB
Go

package app
import (
"bytes"
"io"
"math/rand"
chart "github.com/wcharczuk/go-chart/v2"
. "kjol/vdom"
ui "kjol/webui"
)
var chartLabels = []string{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}
// fixed initial data so the server SSR and the client's first render match.
func fixedChartData() []int { return []int{42, 17, 63, 28, 55, 9, 71} }
func randomValues() []int {
v := make([]int, len(chartLabels))
for i := range v {
v[i] = rand.Intn(95) + 5
}
return v
}
func renderSVG(c interface {
Render(chart.RendererProvider, io.Writer) error
}) string {
var buf bytes.Buffer
if c.Render(chart.SVG, &buf) != nil {
return "<p class=\"text-danger m-0\">chart error</p>"
}
return buf.String()
}
func barSVG(values []int) string {
bars := make([]chart.Value, len(values))
for i, v := range values {
bars[i] = chart.Value{Value: float64(v), Label: chartLabels[i%len(chartLabels)]}
}
return renderSVG(&chart.BarChart{
Title: "Weekly values (bar)",
TitleStyle: chart.Style{FontSize: 15},
Background: chart.Style{Padding: chart.Box{Top: 48, Left: 16, Right: 16, Bottom: 16}},
Height: 320, BarWidth: 48, Bars: bars,
})
}
func pieSVG(values []int) string {
vs := make([]chart.Value, len(values))
for i, v := range values {
vs[i] = chart.Value{Value: float64(v), Label: chartLabels[i%len(chartLabels)]}
}
return renderSVG(&chart.PieChart{
Title: "Share by day (pie)",
TitleStyle: chart.Style{FontSize: 15},
Background: chart.Style{Padding: chart.Box{Top: 48}},
Width: 320, Height: 320, Values: vs,
})
}
//gowasm:page /chart static layout=app
func ChartPage(d Deps) func() *VNode {
data := NewSignal(fixedChartData())
return func() *VNode {
values := data.Get()
return Div(Attr("class", "space-y-6"),
Div(
H2(Attr("class", "text-2xl font-semibold tracking-tight text-text-heading"), Text("Charts — go-chart (SSR + hydrate)")),
P(Attr("class", "mt-1 text-neutral-500"),
Text("Rendered to SVG on the server, hydrated on the client; Shuffle re-renders client-side.")),
),
ui.Button(ui.ButtonProps{Color: ui.ButtonPrimary, Text: "Shuffle data", OnClick: func() { data.Set(randomValues()) }}),
Div(Attr("class", "grid gap-4 lg:grid-cols-12"),
Div(Attr("class", "lg:col-span-7 rounded-default border border-neutral-200 bg-white p-3 shadow-xs overflow-auto"), Raw(barSVG(values))),
Div(Attr("class", "lg:col-span-5 rounded-default border border-neutral-200 bg-white p-3 shadow-xs overflow-auto"), Raw(pieSVG(values))),
),
)
}
}