last annotation helper

This commit is contained in:
Will Charczuk 2016-08-06 15:53:14 -07:00
parent 3b02935861
commit 3607d732d9
3 changed files with 217 additions and 0 deletions

61
examples/min_max/main.go Normal file
View file

@ -0,0 +1,61 @@
package main
import (
"net/http"
"github.com/wcharczuk/go-chart"
)
func drawChart(res http.ResponseWriter, req *http.Request) {
mainSeries := chart.ContinuousSeries{
Name: "A test series",
XValues: chart.Sequence.Float64(1.0, 100.0),
YValues: chart.Sequence.RandomWithAverage(100, 100, 50),
}
minSeries := &chart.MinSeries{
Style: chart.Style{
Show: true,
StrokeColor: chart.ColorAlternateGray,
StrokeDashArray: []float64{5.0, 5.0},
},
InnerSeries: mainSeries,
}
maxSeries := &chart.MaxSeries{
Style: chart.Style{
Show: true,
StrokeColor: chart.ColorAlternateGray,
StrokeDashArray: []float64{5.0, 5.0},
},
InnerSeries: mainSeries,
}
graph := chart.Chart{
YAxis: chart.YAxis{
Style: chart.StyleShow(),
Range: &chart.ContinuousRange{
Min: 25,
Max: 175,
},
},
XAxis: chart.XAxis{
Style: chart.StyleShow(),
},
Series: []chart.Series{
mainSeries,
minSeries,
maxSeries,
chart.LastValueAnnotation(minSeries),
chart.LastValueAnnotation(maxSeries),
},
}
res.Header().Set("Content-Type", "image/png")
graph.Render(chart.PNG, res)
}
func main() {
http.HandleFunc("/", drawChart)
http.ListenAndServe(":8080", nil)
}

View file

@ -0,0 +1,37 @@
package chart
import "fmt"
// LastValueAnnotation returns an annotation series of just the last value of a value provider.
func LastValueAnnotation(innerSeries ValueProvider, vfs ...ValueFormatter) AnnotationSeries {
var vf ValueFormatter
if len(vfs) > 0 {
vf = vfs[0]
} else if typed, isTyped := innerSeries.(ValueFormatterProvider); isTyped {
_, vf = typed.GetValueFormatters()
} else {
vf = FloatValueFormatter
}
var lastValue Value2
if typed, isTyped := innerSeries.(LastValueProvider); isTyped {
lastValue.XValue, lastValue.YValue = typed.GetLastValue()
lastValue.Label = vf(lastValue.YValue)
} else {
lastValue.XValue, lastValue.YValue = innerSeries.GetValue(innerSeries.Len() - 1)
lastValue.Label = vf(lastValue.YValue)
}
var seriesName string
var seriesStyle Style
if typed, isTyped := innerSeries.(Series); isTyped {
seriesName = fmt.Sprintf("%s - Last Value", typed.GetName())
seriesStyle = typed.GetStyle()
}
return AnnotationSeries{
Name: seriesName,
Style: seriesStyle,
Annotations: []Value2{lastValue},
}
}

119
min_max_series.go Normal file
View file

@ -0,0 +1,119 @@
package chart
import "math"
// MinSeries draws a horizontal line at the minimum value of the inner series.
type MinSeries struct {
Name string
Style Style
YAxis YAxisType
InnerSeries ValueProvider
minValue *float64
}
// GetName returns the name of the time series.
func (ms MinSeries) GetName() string {
return ms.Name
}
// GetStyle returns the line style.
func (ms MinSeries) GetStyle() Style {
return ms.Style
}
// GetYAxis returns which YAxis the series draws on.
func (ms MinSeries) GetYAxis() YAxisType {
return ms.YAxis
}
// Len returns the number of elements in the series.
func (ms MinSeries) Len() int {
return ms.InnerSeries.Len()
}
// GetValue gets a value at a given index.
func (ms *MinSeries) GetValue(index int) (x, y float64) {
ms.ensureMinValue()
x, _ = ms.InnerSeries.GetValue(index)
y = *ms.minValue
return
}
// Render renders the series.
func (ms *MinSeries) Render(r Renderer, canvasBox Box, xrange, yrange Range, defaults Style) {
style := ms.Style.InheritFrom(defaults)
Draw.LineSeries(r, canvasBox, xrange, yrange, style, ms)
}
func (ms *MinSeries) ensureMinValue() {
if ms.minValue == nil {
minValue := math.MaxFloat64
var y float64
for x := 0; x < ms.InnerSeries.Len(); x++ {
_, y = ms.InnerSeries.GetValue(x)
if y < minValue {
minValue = y
}
}
ms.minValue = &minValue
}
}
// MaxSeries draws a horizontal line at the maximum value of the inner series.
type MaxSeries struct {
Name string
Style Style
YAxis YAxisType
InnerSeries ValueProvider
maxValue *float64
}
// GetName returns the name of the time series.
func (ms MaxSeries) GetName() string {
return ms.Name
}
// GetStyle returns the line style.
func (ms MaxSeries) GetStyle() Style {
return ms.Style
}
// GetYAxis returns which YAxis the series draws on.
func (ms MaxSeries) GetYAxis() YAxisType {
return ms.YAxis
}
// Len returns the number of elements in the series.
func (ms MaxSeries) Len() int {
return ms.InnerSeries.Len()
}
// GetValue gets a value at a given index.
func (ms *MaxSeries) GetValue(index int) (x, y float64) {
ms.ensureMaxValue()
x, _ = ms.InnerSeries.GetValue(index)
y = *ms.maxValue
return
}
// Render renders the series.
func (ms *MaxSeries) Render(r Renderer, canvasBox Box, xrange, yrange Range, defaults Style) {
style := ms.Style.InheritFrom(defaults)
Draw.LineSeries(r, canvasBox, xrange, yrange, style, ms)
}
func (ms *MaxSeries) ensureMaxValue() {
if ms.maxValue == nil {
maxValue := -math.MaxFloat64
var y float64
for x := 0; x < ms.InnerSeries.Len(); x++ {
_, y = ms.InnerSeries.GetValue(x)
if y > maxValue {
maxValue = y
}
}
ms.maxValue = &maxValue
}
}