Add chart components 216-245; step-aware ticks, font-aware labels
Bars, lines, areas, pies, donuts, radar, histogram, scatter, bubbles, heatmaps, gauge, bullet, funnel, waterfall, treemap, candles, box plots, steps, rings, legend, axis, crosshair, polar area, pyramid, spectrum bars and win-loss strips, each drawn dot by dot. Ticks follow 1-2-5 steps and print as precisely as their step needs; a label row uses micro letters or the pixel font as a whole. Descriptions carry the data in numbers. Bad data panics.
This commit is contained in:
43 files changed
+3336
-1
No files matched your search
@@ -0,0 +1,37 @@
|
||||
package gallery
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/egoist/mygo/ui"
|
||||
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
|
||||
)
|
||||
|
||||
func TestCalendarDemoReadsLocalDays(t *testing.T) {
|
||||
ny, err := time.LoadLocation("America/New_York")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// 21:00 in New York is already the 14th in UTC.
|
||||
now := time.Date(2026, 10, 13, 21, 0, 0, 0, ny)
|
||||
tt := ui.NewTester(func(c *ui.Context) {
|
||||
pixel.Use(c, pixel.Settings{Palette: pixel.SpringDay, Now: func() time.Time { return now }})
|
||||
demoCalendarHeatmap(c, func(string) {})
|
||||
}, 800, 200)
|
||||
r, ok := tt.Find("Play days 2026")
|
||||
if !ok {
|
||||
t.Fatalf("no heatmap in %q", tt.Texts())
|
||||
}
|
||||
// Oct 14 sits at week 41, Wednesday, after four blanks.
|
||||
x, y := int(r.X)/2+41*5, int(r.Y)/2+8+3*5
|
||||
img, shade := tt.Image(), pixel.SpringDay.Colors[pixel.Shade]
|
||||
for j := y; j < y+4; j++ {
|
||||
for i := x; i < x+4; i++ {
|
||||
if c := img.RGBAAt(2*i, 2*j); c.R != shade.R || c.G != shade.G || c.B != shade.B {
|
||||
t.Fatalf("tomorrow's square holds %v at %d,%d", c, i, j)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
package gallery
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand/v2"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"github.com/egoist/mygo/ui"
|
||||
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/chart"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/input"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
|
||||
)
|
||||
|
||||
var chartEntries = []Entry{
|
||||
{216, "BarChart", "柱状图", "chart", "Gold earned per day. Point at a bar to read it.", demoBarChart},
|
||||
{217, "StackedBar", "堆叠柱图", "chart", "Gold under gems, stacked day by day.", demoStackedBar},
|
||||
{218, "HorizontalBar", "条形图", "chart", "Slimes slain, by hero. Brom is not sharing.", demoHorizontalBar},
|
||||
{219, "LineChart", "折线图", "chart", "HP and MP down a dungeon, joined dot by dot.", demoLineChart},
|
||||
{220, "AreaChart", "面积图", "chart", "Gold over a week; the ground under the line dithers.", demoAreaChart},
|
||||
{221, "Sparkline", "迷你图", "chart", "A chart one text line tall. It fits in a sentence.", demoSparkline},
|
||||
{222, "PieChart", "饼图", "chart", "Where the loot went, sector by sector, dot by dot.", demoPieChart},
|
||||
{223, "DonutChart", "环形图", "chart", "A pie with a hole; the total waits inside.", demoDonutChart},
|
||||
{224, "RadarChart", "雷达图", "chart", "Six stats on a hexagon web. LEVEL UP and watch it grow.", demoRadarChart},
|
||||
{225, "Histogram", "直方图", "chart", "Damage rolls in bins. ROLL throws ten more.", demoHistogram},
|
||||
{226, "ScatterPlot", "散点图", "chart", "Every hit by distance and damage, one 2×2 dot each.", demoScatterPlot},
|
||||
{227, "BubbleChart", "气泡图", "chart", "Towns by trade and danger, sized by how many live there.", demoBubbleChart},
|
||||
{228, "Heatmap", "热力图", "chart", "Raids by day and hour. Hot cells dither red.", demoHeatmap},
|
||||
{229, "CalendarHeatmap", "日历热力图", "chart", "A year of play, a square a day. A commit graph for slimes.", demoCalendarHeatmap},
|
||||
{230, "Gauge", "仪表", "chart", "Push the throttle; the needle follows.", demoGauge},
|
||||
}
|
||||
|
||||
type chartDemo struct {
|
||||
stats []float64
|
||||
rolls []float64
|
||||
dice *rand.Rand
|
||||
throttle float64
|
||||
hidden []bool
|
||||
since time.Time
|
||||
play bool
|
||||
matches []int
|
||||
}
|
||||
|
||||
func chartState(c *ui.Context) *chartDemo {
|
||||
return ui.Local(c.Root(), demoKey("chart"), func() chartDemo {
|
||||
s := chartDemo{stats: []float64{4, 3, 2, 4, 3, 2}, dice: rand.New(rand.NewPCG(1, 2)), throttle: 40,
|
||||
hidden: []bool{false, false, false}, play: true, matches: []int{1, 1, -1, 1, 0, -1, 1, 1}}
|
||||
for range 30 {
|
||||
s.rolls = append(s.rolls, roll(s.dice))
|
||||
}
|
||||
return s
|
||||
})
|
||||
}
|
||||
|
||||
// roll throws two dice.
|
||||
func roll(r *rand.Rand) float64 { return float64(r.IntN(6) + r.IntN(6) + 2) }
|
||||
|
||||
var week = []string{"MON", "TUE", "WED", "THU", "FRI"}
|
||||
|
||||
// heroes are three HP series with fixed colors.
|
||||
var heroes = []chart.Series{
|
||||
{Name: "Aria", Values: []float64{30, 26, 28, 18, 24}, Slot: pixel.Good},
|
||||
{Name: "Brom", Values: []float64{40, 34, 22, 26, 12}, Slot: pixel.Warn},
|
||||
{Name: "Cid", Values: []float64{18, 20, 16, 22, 20}, Slot: pixel.Info},
|
||||
}
|
||||
|
||||
func demoBarChart(c *ui.Context, log func(string)) {
|
||||
chart.BarChart(c, "Gold per day", week, []float64{120, 340, 90, 260, 410}, chart.BarChartOptions{Width: 200, Height: 90})
|
||||
}
|
||||
|
||||
func demoStackedBar(c *ui.Context, log func(string)) {
|
||||
chart.StackedBar(c, "Loot per day", week, []chart.Series{
|
||||
{Name: "Gold", Values: []float64{12, 30, 8, 22, 18}, Slot: pixel.Warn},
|
||||
{Name: "Gems", Values: []float64{4, 6, 12, 2, 9}, Slot: pixel.Magic},
|
||||
}, chart.StackedBarOptions{Width: 200, Height: 90})
|
||||
}
|
||||
|
||||
func demoHorizontalBar(c *ui.Context, log func(string)) {
|
||||
chart.HorizontalBar(c, "Slimes slain", []string{"Aria", "Brom", "Cid", "Dax"}, []float64{48, 112, 37, 64}, chart.HorizontalBarOptions{Width: 200})
|
||||
}
|
||||
|
||||
func demoLineChart(c *ui.Context, log func(string)) {
|
||||
floors := []string{"B1", "B2", "B3", "B4", "B5", "B6"}
|
||||
chart.LineChart(c, "Dungeon run", floors, []chart.Series{
|
||||
{Name: "HP", Values: []float64{50, 44, 47, 30, 36, 12}, Slot: pixel.Good},
|
||||
{Name: "MP", Values: []float64{20, 16, 8, 12, 4, 6}, Slot: pixel.Info},
|
||||
}, chart.LineChartOptions{Width: 200, Height: 90})
|
||||
}
|
||||
|
||||
func demoAreaChart(c *ui.Context, log func(string)) {
|
||||
chart.AreaChart(c, "Gold", week, []float64{120, 180, 150, 260, 310}, chart.AreaChartOptions{Width: 200, Height: 90, Slot: pixel.Warn})
|
||||
}
|
||||
|
||||
func demoSparkline(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
ui.Column(c).Gap(k.D(2)).Children(func() {
|
||||
for _, r := range []struct {
|
||||
name, now string
|
||||
values []float64
|
||||
slot pixel.Slot
|
||||
}{
|
||||
{"Ping", "42 ms", []float64{40, 44, 39, 61, 45, 42, 38, 42}, pixel.Info},
|
||||
{"FPS", "60", []float64{60, 60, 58, 41, 59, 60, 60, 60}, pixel.Good},
|
||||
{"Gold", "1.2K", []float64{300, 420, 380, 650, 700, 980, 1100, 1200}, pixel.Warn},
|
||||
} {
|
||||
ui.Row(c).Gap(k.D(6)).AlignItems(ui.Center).Children(func() {
|
||||
ui.Box(c).Width(k.D(36)).Children(func() { pixel.Text(c, r.name, pixel.TextOptions{Slot: pixel.Faint}) })
|
||||
chart.Sparkline(c, r.name, r.values, chart.SparklineOptions{Slot: r.slot})
|
||||
pixel.Text(c, r.now, pixel.TextOptions{})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func demoPieChart(c *ui.Context, log func(string)) {
|
||||
chart.PieChart(c, "Loot", []chart.Slice{{Name: "Gold", Value: 52, Slot: pixel.Warn}, {Name: "Gems", Value: 23, Slot: pixel.Magic},
|
||||
{Name: "Potions", Value: 15, Slot: pixel.Bad}, {Name: "Junk", Value: 10, Slot: pixel.Faint}}, chart.PieChartOptions{Size: 80})
|
||||
}
|
||||
|
||||
func demoDonutChart(c *ui.Context, log func(string)) {
|
||||
chart.DonutChart(c, "Party gold", []chart.Slice{{Name: "Aria", Value: 120}, {Name: "Brom", Value: 340}, {Name: "Cid", Value: 90}}, chart.DonutChartOptions{Size: 80})
|
||||
}
|
||||
|
||||
func demoRadarChart(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
s := chartState(c)
|
||||
ui.Row(c).Gap(k.D(8)).AlignItems(ui.Center).Children(func() {
|
||||
chart.RadarChart(c, "Hero", []string{"STR", "DEX", "INT", "VIT", "AGI", "LUK"}, s.stats, chart.RadarChartOptions{Max: 10, Size: 96, Slot: pixel.Accent})
|
||||
maxed := slices.Min(s.stats) >= 10
|
||||
if input.Button(c, "LEVEL UP", input.ButtonOptions{Disabled: maxed}).Clicked {
|
||||
for i := range s.stats {
|
||||
s.stats[i] = min(10, s.stats[i]+float64(1+i%2))
|
||||
}
|
||||
log(fmt.Sprintf("STR %g, DEX %g", s.stats[0], s.stats[1]))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func demoHistogram(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
s := chartState(c)
|
||||
ui.Row(c).Gap(k.D(8)).AlignItems(ui.Center).Children(func() {
|
||||
chart.Histogram(c, "2d6 rolls", s.rolls, chart.HistogramOptions{Bins: 11, Width: 200, Height: 90})
|
||||
if input.Button(c, "ROLL", input.ButtonOptions{}).Clicked {
|
||||
for range 10 {
|
||||
s.rolls = append(s.rolls, roll(s.dice))
|
||||
}
|
||||
log(fmt.Sprintf("%d rolls", len(s.rolls)))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func demoScatterPlot(c *ui.Context, log func(string)) {
|
||||
hits := []chart.Point{{X: 1, Y: 12}, {X: 2, Y: 10}, {X: 2, Y: 14}, {X: 3, Y: 9}, {X: 4, Y: 8}, {X: 5, Y: 8}, {X: 5, Y: 3},
|
||||
{X: 6, Y: 6}, {X: 7, Y: 5}, {X: 8, Y: 4}, {X: 8, Y: 9}, {X: 9, Y: 2}}
|
||||
chart.ScatterPlot(c, "Hits", hits, chart.ScatterPlotOptions{Width: 200, Height: 90, Slot: pixel.Bad})
|
||||
}
|
||||
|
||||
func demoBubbleChart(c *ui.Context, log func(string)) {
|
||||
towns := []chart.Point{{X: 2, Y: 8, Size: 120}, {X: 5, Y: 3, Size: 900}, {X: 7, Y: 6, Size: 300}, {X: 9, Y: 9, Size: 40}}
|
||||
chart.BubbleChart(c, "Towns", towns, chart.BubbleChartOptions{Width: 200, Height: 90, Slot: pixel.Info})
|
||||
}
|
||||
|
||||
func demoHeatmap(c *ui.Context, log func(string)) {
|
||||
chart.Heatmap(c, "Raids", []string{"MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"}, []string{"AM", "NOON", "PM", "NIGHT"}, [][]float64{
|
||||
{1, 2, 3, 6}, {0, 2, 4, 7}, {1, 1, 3, 5}, {0, 3, 5, 8}, {2, 4, 7, 12}, {5, 8, 10, 14}, {6, 7, 9, 4},
|
||||
}, chart.HeatmapOptions{Cell: 12})
|
||||
}
|
||||
|
||||
func demoCalendarHeatmap(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
now := k.Now()
|
||||
// Tomorrow's square lights up at midnight.
|
||||
k.At(c, time.Date(now.Year(), now.Month(), now.Day()+1, 0, 0, 0, 0, now.Location()))
|
||||
// Days come as UTC dates; today is the local date.
|
||||
today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC)
|
||||
chart.CalendarHeatmap(c, "Play days", now.Year(), func(d time.Time) int {
|
||||
if today.Before(d) {
|
||||
return 0
|
||||
}
|
||||
// Weekends run hotter; the rest is a made-up habit.
|
||||
n := (d.YearDay()*d.YearDay()*7 + d.YearDay()*3) % 10
|
||||
if d.Weekday() == time.Saturday || d.Weekday() == time.Sunday {
|
||||
n += 4
|
||||
}
|
||||
return min(4, n/3)
|
||||
}, chart.CalendarHeatmapOptions{})
|
||||
}
|
||||
|
||||
func demoGauge(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
s := chartState(c)
|
||||
ui.Row(c).Gap(k.D(8)).AlignItems(ui.Center).Children(func() {
|
||||
chart.Gauge(c, "Speed", s.throttle, chart.GaugeOptions{Size: 80})
|
||||
if input.Slider(c, "Throttle", &s.throttle, input.SliderOptions{Max: 100}).Changed {
|
||||
log(fmt.Sprintf("speed %.0f", s.throttle))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package gallery
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/egoist/mygo/ui"
|
||||
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/chart"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/input"
|
||||
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
|
||||
)
|
||||
|
||||
var plotEntries = []Entry{
|
||||
{231, "BulletChart", "子弹图", "chart", "Progress against a goal, over bands of poor, fine and great.", demoBulletChart},
|
||||
{232, "Funnel", "漏斗图", "chart", "From SEEN to BOUGHT at the item shop. Most just window-shop.", demoFunnel},
|
||||
{233, "Waterfall", "瀑布图", "chart", "Your wallet through a day: green steps up, red steps down.", demoWaterfall},
|
||||
{234, "Treemap", "矩形树图", "chart", "The bag by weight, tiled into near squares.", demoTreemap},
|
||||
{235, "Candlestick", "K线图", "chart", "Potion prices. Green days rose, red days fell.", demoCandlestick},
|
||||
{236, "BoxPlot", "箱线图", "chart", "Rolls by die: the middle half in the box, the ends on whiskers.", demoBoxPlot},
|
||||
{237, "StepChart", "阶梯图", "chart", "Hero level by week. It only ever steps.", demoStepChart},
|
||||
{238, "ProgressRing", "进度环", "chart", "Clockwise from twelve, a pixel arc at a time.", demoProgressRing},
|
||||
{239, "Legend", "图例", "chart", "Click a hero to hide or show their line.", demoLegend},
|
||||
{240, "Axis", "坐标轴", "chart", "Ticks and micro labels, across or down.", demoAxis},
|
||||
{241, "Crosshair", "十字线", "chart", "Hover the chart; the crosshair reads every line.", demoCrosshair},
|
||||
{242, "PolarArea", "极坐标图", "chart", "Equal turns, each reaching out by its value.", demoPolarArea},
|
||||
{243, "Pyramid", "金字塔图", "chart", "Heroes and monsters back to back, by level.", demoPyramid},
|
||||
{244, "SpectrumBars", "频谱条", "chart", "Bars dance in segments; peak dots fall behind them.", demoSpectrumBars},
|
||||
{245, "WinLoss", "胜负图", "chart", "Wins up, losses down, draws a dash. PLAY for one more.", demoWinLoss},
|
||||
}
|
||||
|
||||
func demoBulletChart(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
ui.Column(c).Gap(k.D(4)).Children(func() {
|
||||
pixel.Text(c, "Quest XP: 62 of 80", pixel.TextOptions{Slot: pixel.Faint})
|
||||
chart.BulletChart(c, "Quest XP", 62, 80, []float64{40, 70, 100}, chart.BulletChartOptions{Width: 200})
|
||||
})
|
||||
}
|
||||
|
||||
func demoFunnel(c *ui.Context, log func(string)) {
|
||||
chart.Funnel(c, "Item shop", []chart.Slice{{Name: "SEEN", Value: 120}, {Name: "CLICKED", Value: 64}, {Name: "IN CART", Value: 30},
|
||||
{Name: "BOUGHT", Value: 12}}, chart.FunnelOptions{Width: 200})
|
||||
}
|
||||
|
||||
func demoWaterfall(c *ui.Context, log func(string)) {
|
||||
chart.Waterfall(c, "Wallet", []string{"QUEST", "INN", "SHOP", "LOOT", "TAX"}, []float64{40, -8, -25, 18, -5}, chart.WaterfallOptions{Width: 200, Height: 90})
|
||||
}
|
||||
|
||||
func demoTreemap(c *ui.Context, log func(string)) {
|
||||
chart.Treemap(c, "Bag weight", []chart.Slice{{Name: "ARMOR", Value: 10}, {Name: "SWORD", Value: 8}, {Name: "SHIELD", Value: 6},
|
||||
{Name: "HERBS", Value: 2}, {Name: "KEYS", Value: 1}, {Name: "MAP", Value: 1}}, chart.TreemapOptions{Width: 200, Height: 90})
|
||||
}
|
||||
|
||||
func demoCandlestick(c *ui.Context, log func(string)) {
|
||||
chart.Candlestick(c, "Potion price", []chart.Candle{
|
||||
{Label: "MON", Open: 10, High: 14, Low: 9, Close: 13}, {Label: "TUE", Open: 13, High: 15, Low: 8, Close: 9},
|
||||
{Label: "WED", Open: 9, High: 12, Low: 7, Close: 11}, {Label: "THU", Open: 11, High: 18, Low: 11, Close: 17},
|
||||
{Label: "FRI", Open: 17, High: 17, Low: 12, Close: 13},
|
||||
}, chart.CandlestickOptions{Width: 200, Height: 90})
|
||||
}
|
||||
|
||||
func demoBoxPlot(c *ui.Context, log func(string)) {
|
||||
chart.BoxPlot(c, "Rolls", []chart.Series{
|
||||
{Name: "D6", Values: []float64{1, 2, 3, 3, 4, 5, 6}},
|
||||
{Name: "D8", Values: []float64{1, 3, 4, 5, 5, 7, 8}},
|
||||
{Name: "D12", Values: []float64{2, 4, 6, 7, 9, 11, 12}},
|
||||
}, chart.BoxPlotOptions{Width: 200, Height: 90})
|
||||
}
|
||||
|
||||
func demoStepChart(c *ui.Context, log func(string)) {
|
||||
chart.StepChart(c, "Level", []string{"W1", "W2", "W3", "W4", "W5", "W6"}, []float64{1, 3, 3, 4, 7, 8}, chart.StepChartOptions{Width: 200, Height: 90, Slot: pixel.Magic})
|
||||
}
|
||||
|
||||
func demoProgressRing(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
s := chartState(c)
|
||||
// The pretend download takes four seconds.
|
||||
done := k.Since(c, s.since, 10, 40)
|
||||
ui.Row(c).Gap(k.D(8)).AlignItems(ui.Center).Children(func() {
|
||||
chart.ProgressRing(c, "Download", float64(done)/40, chart.ProgressRingOptions{Size: 48})
|
||||
if input.Button(c, "DOWNLOAD", input.ButtonOptions{Disabled: done < 40}).Clicked {
|
||||
s.since = k.Now()
|
||||
log("downloading more RAM")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func demoLegend(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
s := chartState(c)
|
||||
var shown []chart.Series
|
||||
for i, h := range heroes {
|
||||
if !s.hidden[i] {
|
||||
shown = append(shown, h)
|
||||
}
|
||||
}
|
||||
ui.Column(c).Gap(k.D(4)).Children(func() {
|
||||
if chart.Legend(c, "Heroes", heroes, s.hidden, chart.LegendOptions{}).Changed {
|
||||
log(fmt.Sprintf("hidden %v", s.hidden))
|
||||
}
|
||||
chart.LineChart(c, "Hero HP", week, shown, chart.LineChartOptions{Width: 200, Height: 90})
|
||||
})
|
||||
}
|
||||
|
||||
func demoAxis(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
ui.Row(c).Gap(k.D(12)).AlignItems(ui.Center).Children(func() {
|
||||
chart.Axis(c, chart.AxisOptions{Labels: []string{"LOW", "MID", "HIGH"}, Vertical: true, Length: 60})
|
||||
chart.Axis(c, chart.AxisOptions{Min: 0, Max: 250, Length: 160})
|
||||
})
|
||||
}
|
||||
|
||||
func demoCrosshair(c *ui.Context, log func(string)) {
|
||||
chart.Crosshair(c, "Hero HP", week, heroes, chart.CrosshairOptions{Width: 200, Height: 90})
|
||||
}
|
||||
|
||||
func demoPolarArea(c *ui.Context, log func(string)) {
|
||||
chart.PolarArea(c, "Rain", []chart.Slice{{Name: "SPRING", Value: 6, Slot: pixel.Good}, {Name: "SUMMER", Value: 3, Slot: pixel.Warn},
|
||||
{Name: "AUTUMN", Value: 8, Slot: pixel.Bad}, {Name: "WINTER", Value: 4, Slot: pixel.Info}}, chart.PolarAreaOptions{Size: 80})
|
||||
}
|
||||
|
||||
func demoPyramid(c *ui.Context, log func(string)) {
|
||||
chart.Pyramid(c, "By level", []string{"LV 1-9", "LV 10-19", "LV 20-29", "LV 30+"},
|
||||
chart.Series{Name: "HEROES", Values: []float64{40, 26, 12, 4}, Slot: pixel.Info},
|
||||
chart.Series{Name: "MONSTERS", Values: []float64{60, 30, 18, 9}, Slot: pixel.Bad}, chart.PyramidOptions{Width: 220})
|
||||
}
|
||||
|
||||
func demoSpectrumBars(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
s := chartState(c)
|
||||
n := 0
|
||||
if s.play && !k.Reduce() {
|
||||
n = k.Tick(c, 8)
|
||||
}
|
||||
levels := make([]float64, 12)
|
||||
for i := range levels {
|
||||
// A made-up song: a slow swell times a quick wobble.
|
||||
t, f := float64(n), float64(i)
|
||||
levels[i] = 0.5 + 0.45*math.Sin(t*0.7+f*1.3)*math.Sin(t*0.13+f*0.4)
|
||||
}
|
||||
ui.Row(c).Gap(k.D(8)).AlignItems(ui.Center).Children(func() {
|
||||
chart.SpectrumBars(c, "Music", levels, chart.SpectrumBarsOptions{Segments: 12})
|
||||
if input.Toggle(c, "PLAY", &s.play, input.ToggleOptions{Size: input.Small}).Changed {
|
||||
log(fmt.Sprintf("play %v", s.play))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func demoWinLoss(c *ui.Context, log func(string)) {
|
||||
k := pixel.K(c)
|
||||
s := chartState(c)
|
||||
ui.Row(c).Gap(k.D(8)).AlignItems(ui.Center).Children(func() {
|
||||
chart.WinLoss(c, "Arena", s.matches, chart.WinLossOptions{})
|
||||
if input.Button(c, "PLAY", input.ButtonOptions{Size: input.Small}).Clicked {
|
||||
r := s.dice.IntN(3) - 1
|
||||
// The strip keeps the last twenty matches.
|
||||
s.matches = append(s.matches[max(0, len(s.matches)-19):], r)
|
||||
log([]string{"lost", "draw", "won"}[r+1])
|
||||
}
|
||||
})
|
||||
}
|
||||
+1
-1
@@ -56,7 +56,7 @@ var Categories = []Category{
|
||||
{"tabletop", "Tabletop", "桌游", icon.Crown},
|
||||
}
|
||||
|
||||
var entries = slices.Concat(foundationEntries, layoutEntries, textEntries, displayEntries, inputEntries, controlEntries, feedbackEntries, navigationEntries, dataEntries, recordEntries, overlayEntries, popupEntries, datetimeEntries, timeEntries)
|
||||
var entries = slices.Concat(foundationEntries, layoutEntries, textEntries, displayEntries, inputEntries, controlEntries, feedbackEntries, navigationEntries, dataEntries, recordEntries, overlayEntries, popupEntries, datetimeEntries, timeEntries, chartEntries, plotEntries)
|
||||
|
||||
func Entries() []Entry { return entries }
|
||||
|
||||
|
||||
Reference in new issue
Block a user