feat: support to set the first axis
This commit is contained in:
parent
29a5ece545
commit
20e8d4a078
4 changed files with 102 additions and 2 deletions
4
axis.go
4
axis.go
|
|
@ -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,
|
||||||
|
|
|
||||||
82
examples/time_line_chart/main.go
Normal file
82
examples/time_line_chart/main.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
15
painter.go
15
painter.go
|
|
@ -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 {
|
||||||
|
|
|
||||||
3
xaxis.go
3
xaxis.go
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue