feat: support to set the first axis

This commit is contained in:
vicanso 2023-02-25 14:04:30 +08:00
parent 29a5ece545
commit 20e8d4a078
4 changed files with 102 additions and 2 deletions

View file

@ -63,6 +63,8 @@ type AxisOption struct {
StrokeWidth float64 StrokeWidth float64
// The length of the axis tick // The length of the axis tick
TickLength int TickLength int
// The first axis
FirstAxis int
// The margin value of label // The margin value of label
LabelMargin int LabelMargin int
// The font size of label // The font size of label
@ -255,6 +257,7 @@ func (a *axisPainter) Render() (Box, error) {
Length: tickLength, Length: tickLength,
Unit: unit, Unit: unit,
Orient: orient, Orient: orient,
First: opt.FirstAxis,
}) })
p.LineStroke([]Point{ p.LineStroke([]Point{
{ {
@ -273,6 +276,7 @@ func (a *axisPainter) Render() (Box, error) {
Top: labelPaddingTop, Top: labelPaddingTop,
Right: labelPaddingRight, Right: labelPaddingRight,
})).MultiText(MultiTextOption{ })).MultiText(MultiTextOption{
First: opt.FirstAxis,
Align: textAlign, Align: textAlign,
TextList: data, TextList: data,
Orient: orient, Orient: orient,

View file

@ -0,0 +1,82 @@
package main
import (
"crypto/rand"
"fmt"
"io/ioutil"
"math/big"
"os"
"path/filepath"
"time"
"github.com/vicanso/go-charts/v2"
)
func writeFile(buf []byte) error {
tmpPath := "./tmp"
err := os.MkdirAll(tmpPath, 0700)
if err != nil {
return err
}
file := filepath.Join(tmpPath, "time-line-chart.png")
err = ioutil.WriteFile(file, buf, 0600)
if err != nil {
return err
}
return nil
}
func main() {
xAxisValue := []string{}
values := []float64{}
now := time.Now()
firstAxis := 0
for i := 0; i < 300; i++ {
// 设置首个axis为xx:00的时间点
if firstAxis == 0 && now.Minute() == 0 {
firstAxis = i
}
xAxisValue = append(xAxisValue, now.Format("15:04"))
now = now.Add(time.Minute)
value, _ := rand.Int(rand.Reader, big.NewInt(100))
values = append(values, float64(value.Int64()))
}
p, err := charts.LineRender(
[][]float64{
values,
},
charts.TitleTextOptionFunc("Line"),
charts.XAxisDataOptionFunc(xAxisValue, charts.FalseFlag()),
charts.LegendLabelsOptionFunc([]string{
"Demo",
}, "50"),
func(opt *charts.ChartOption) {
opt.XAxis.FirstAxis = firstAxis
// 必须要比计算得来的最小值更大(每60分钟)
opt.XAxis.SplitNumber = 60
opt.Legend.Padding = charts.Box{
Top: 5,
Bottom: 10,
}
opt.SymbolShow = charts.FalseFlag()
opt.LineStrokeWidth = 1
opt.ValueFormatter = func(f float64) string {
return fmt.Sprintf("%.0f", f)
}
},
)
if err != nil {
panic(err)
}
buf, err := p.Bytes()
if err != nil {
panic(err)
}
err = writeFile(buf)
if err != nil {
panic(err)
}
}

View file

@ -59,6 +59,8 @@ type PainterOptions struct {
type PainterOption func(*Painter) type PainterOption func(*Painter)
type TicksOption struct { type TicksOption struct {
// the first tick
First int
Length int Length int
Orient string Orient string
Count int Count int
@ -74,6 +76,8 @@ type MultiTextOption struct {
// The text rotation of label // The text rotation of label
TextRotation float64 TextRotation float64
Offset Box Offset Box
// The first text index
First int
} }
type GridOption struct { type GridOption struct {
@ -616,6 +620,7 @@ func (p *Painter) Ticks(opt TicksOption) *Painter {
return p return p
} }
count := opt.Count count := opt.Count
first := opt.First
width := p.Width() width := p.Width()
height := p.Height() height := p.Height()
unit := 1 unit := 1
@ -630,7 +635,10 @@ func (p *Painter) Ticks(opt TicksOption) *Painter {
values = autoDivide(width, count) values = autoDivide(width, count)
} }
for index, value := range values { for index, value := range values {
if index%unit != 0 { if index < first {
continue
}
if (index-first)%unit != 0 {
continue continue
} }
if isVertical { if isVertical {
@ -688,7 +696,10 @@ func (p *Painter) MultiText(opt MultiTextOption) *Painter {
isTextRotation := opt.TextRotation != 0 isTextRotation := opt.TextRotation != 0
offset := opt.Offset offset := opt.Offset
for index, text := range opt.TextList { for index, text := range opt.TextList {
if opt.Unit != 0 && index%opt.Unit != showIndex { if index < opt.First {
continue
}
if opt.Unit != 0 && (index-opt.First)%opt.Unit != showIndex {
continue continue
} }
if isTextRotation { if isTextRotation {

View file

@ -50,6 +50,8 @@ type XAxisOption struct {
FontColor Color FontColor Color
// The text rotation of label // The text rotation of label
TextRotation float64 TextRotation float64
// The first axis
FirstAxis int
// The offset of label // The offset of label
LabelOffset Box LabelOffset Box
isValueAxis bool isValueAxis bool
@ -87,6 +89,7 @@ func (opt *XAxisOption) ToAxisOption() AxisOption {
SplitLineColor: opt.Theme.GetAxisSplitLineColor(), SplitLineColor: opt.Theme.GetAxisSplitLineColor(),
TextRotation: opt.TextRotation, TextRotation: opt.TextRotation,
LabelOffset: opt.LabelOffset, LabelOffset: opt.LabelOffset,
FirstAxis: opt.FirstAxis,
} }
if opt.isValueAxis { if opt.isValueAxis {
axisOpt.SplitLineShow = true axisOpt.SplitLineShow = true