Files
via/internal/examples/realtimechart/main.go
Ryan Hamamura a7ace9099f feat: replace log with rs/zerolog for structured logging
Switch from the standard library log package to rs/zerolog with
ConsoleWriter for colorful terminal output in dev mode and JSON
output in production. Users can now provide their own logger via
Options.Logger or set the level via Options.LogLevel.
2026-01-31 08:18:24 -10:00

174 lines
4.2 KiB
Go

package main
import (
"fmt"
"math/rand"
"time"
"github.com/ryanhamamura/via"
// "github.com/go-via/via-plugin-picocss/picocss"
"github.com/ryanhamamura/via/h"
)
func main() {
v := via.New()
v.Config(via.Options{
LogLevel: via.LogLevelDebug,
DevMode: true,
Plugins: []via.Plugin{
// picocss.Default,
},
})
v.AppendToHead(
h.Script(h.Src("https://unpkg.com/echarts@6.0.0/dist/echarts.min.js")),
)
v.Page("/", func(c *via.Context) {
isLive := true
isLiveSig := c.Signal("on")
refreshRate := c.Signal("24")
computedTickDuration := func() time.Duration {
return 1000 / time.Duration(refreshRate.Int()) * time.Millisecond
}
updateData := c.OnInterval(computedTickDuration(), func() {
ts := time.Now().UnixMilli()
val := rand.ExpFloat64() * 10
c.ExecScript(fmt.Sprintf(`
if (myChart) {
myChart.appendData({seriesIndex: 0, data: [[%d, %f]]});
myChart.setOption({},{notMerge:false,lazyUpdate:true});
};
`, ts, val))
})
updateData.Start()
updateRefreshRate := c.Action(func() {
updateData.UpdateInterval(computedTickDuration())
})
toggleIsLive := c.Action(func() {
isLive = isLiveSig.Bool()
if isLive {
updateData.Start()
} else {
updateData.Stop()
}
})
c.View(func() h.H {
return h.Div(h.Style("overflow-x:hidden"),
h.Section(h.Class("container"),
h.Nav(
h.Ul(h.Li(h.H3(h.Text("⚡Via")))),
h.Ul(
h.Li(h.A(h.H5(h.Text("About")), h.Href("https://github.com/go-via/via"))),
h.Li(h.A(h.H5(h.Text("Resources")), h.Href("https://github.com/orgs/go-via/repositories"))),
h.Li(h.A(h.H5(h.Text("Say hi!")), h.Href("http://github.com/go-via/via/discussions"))),
),
),
),
h.Div(
h.Div(h.ID("chart"), h.DataIgnoreMorph(), h.Style("width:100%;height:400px;"),
h.Script(h.Raw(`
var prefersDark = window.matchMedia('(prefers-color-scheme: dark)');
var myChart = echarts.init(document.getElementById('chart'), prefersDark.matches ? 'dark' : 'light');
var option = {
backgroundColor: prefersDark.matches ? 'transparent' : '#ffffff',
animationDurationUpdate: 0, // affects updates/redraws
tooltip: {
trigger: 'axis',
position: function (pt) {
return [pt[0], '10%'];
},
syncStrategy: 'closestSampledPoint',
backgroundColor: prefersDark.matches ? '#13171fc0' : '#eeeeeec0',
extraCssText: 'backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);'
},
title: {
left: 'center',
text: '📈 Real-Time Chart Example'
},
xAxis: {
type: 'time',
boundaryGap: false,
axisLabel: {
hideOverlap: true
}
},
yAxis: {
type: 'value',
boundaryGap: [0, '100%'],
min: 0,
max: 100
},
dataZoom: [
{
type: 'inside',
start: 1,
end: 100
},
{
start: 0,
end: 100
}
],
series: [
{
name: 'Fake Data',
type: 'line',
symbol: 'none',
sampling: 'max',
itemStyle: {
color: '#e8ae01'
},
lineStyle: { color: '#e8ae01'},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: '#fecc63'
},
{
offset: 1,
color: '#c79400'
}
])
},
large: true,
data: []
}
]
};
option && myChart.setOption(option);
`)),
),
h.Section(
h.Article(
h.H5(h.Text("Controls")),
h.Hr(),
h.Div(h.Class("grid"),
h.FieldSet(
h.Legend(h.Text("Live Data")),
h.Input(h.Type("checkbox"), h.Role("switch"), isLiveSig.Bind(), toggleIsLive.OnChange()),
),
h.Label(h.Text("Refresh Rate (Hz) ― "), refreshRate.Text(),
h.Input(h.Type("range"), h.Attr("min", "1"), h.Attr("max", "200"), refreshRate.Bind(), updateRefreshRate.OnChange()),
),
),
),
),
),
)
})
})
v.Start()
}