Skip to content

Instantly share code, notes, and snippets.

@peterhellberg
Created October 11, 2018 19:41
Show Gist options
  • Save peterhellberg/87f6b06b603afd7ca582811e52855013 to your computer and use it in GitHub Desktop.
Save peterhellberg/87f6b06b603afd7ca582811e52855013 to your computer and use it in GitHub Desktop.
go-chart rendered by Ebiten
package main
import (
"container/ring"
"image"
"log"
"math/rand"
"os"
"time"
"github.com/hajimehoshi/ebiten"
"github.com/wcharczuk/go-chart"
"github.com/wcharczuk/go-chart/drawing"
"github.com/wcharczuk/go-chart/seq"
)
const w, h = 960, 540
func main() {
s := ebiten.DeviceScaleFactor()
g := NewGraph(100, s, func(g *Graph) {
g.Background = chart.Style{
Padding: chart.Box{
Top: 25,
Left: 25,
Right: 25,
Bottom: 25,
},
FillColor: drawing.ColorFromHex("efefef"),
}
g.YAxis = chart.YAxis{
Style: chart.Style{
Show: true,
},
Range: &chart.ContinuousRange{
Max: 4,
Min: -4,
},
}
})
go generateRandomData(g, 64*time.Millisecond)
m := g.Image()
go func() {
for range time.NewTicker(64 * time.Millisecond).C {
m = g.Image()
}
}()
update := func(screen *ebiten.Image) error {
if ebiten.IsKeyPressed(ebiten.KeyEscape) || ebiten.IsKeyPressed(ebiten.KeyQ) {
os.Exit(0)
}
if !ebiten.IsDrawingSkipped() {
screen.ReplacePixels(m.Pix)
}
return nil
}
if err := ebiten.Run(update, int(w*s), int(h*s), 1/s, "Ebiten + go-chart"); err != nil {
log.Fatal(err)
}
}
type Graph struct {
chart.Chart
*ring.Ring
}
func NewGraph(n int, s float64, options ...func(*Graph)) *Graph {
g := &Graph{chart.Chart{
Width: int(float64(w) * s),
Height: int(float64(h) * s),
},
ring.New(n),
}
for i := 0; i < g.Len(); i++ {
g.Value = 0.0
g.Ring = g.Next()
}
for _, o := range options {
o(g)
}
return g
}
func (g *Graph) Set(v float64) {
g.Value = v
g.Ring = g.Next()
}
func (g *Graph) Image() *image.RGBA {
var yValues []float64
g.Do(func(x interface{}) {
if x != nil {
yValues = append(yValues, x.(float64))
}
})
mainSeries := chart.ContinuousSeries{
Style: chart.Style{
Show: true,
StrokeColor: chart.GetDefaultColor(0).WithAlpha(96),
FillColor: chart.GetDefaultColor(0).WithAlpha(32),
},
XValues: seq.Range(1.0, float64(len(yValues))),
YValues: yValues,
}
smaSeries := &chart.SMASeries{
InnerSeries: mainSeries,
}
g.Series = []chart.Series{mainSeries, smaSeries}
iw := &chart.ImageWriter{}
g.Render(chart.PNG, iw)
m, _ := iw.Image()
return m.(*image.RGBA)
}
func generateRandomData(g *Graph, d time.Duration) {
for range time.NewTicker(d).C {
v := g.Value.(float64)
switch {
case v > 2:
g.Set(v - rand.Float64())
case v < -2:
g.Set(v + rand.Float64())
default:
g.Set(v + 2*rand.Float64() - 0.5)
}
}
}
@peterhellberg
Copy link
Author

ebiten-chart

@OpoOpo
Copy link

OpoOpo commented Dec 3, 2018

Is it possible to render graph even if the window is not focused?

@peterhellberg
Copy link
Author

@OpoOpo Yes, you just call ebiten.SetRunnableInBackground(true) at the start of main

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment