last annotation helper
This commit is contained in:
parent
3b02935861
commit
3607d732d9
3 changed files with 217 additions and 0 deletions
61
examples/min_max/main.go
Normal file
61
examples/min_max/main.go
Normal 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)
|
||||||
|
}
|
37
last_value_annotation_series.go
Normal file
37
last_value_annotation_series.go
Normal 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
119
min_max_series.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue