refactor: default render function for axis

This commit is contained in:
vicanso 2022-06-12 19:58:36 +08:00
parent c4045cfbbe
commit 72e11e49b1
3 changed files with 97 additions and 49 deletions

View file

@ -29,14 +29,90 @@ type Renderer interface {
type defaultRenderOption struct { type defaultRenderOption struct {
Theme ColorPalette Theme ColorPalette
Padding Box Padding Box
SeriesList SeriesList
// The y axis option
YAxisOptions []YAxisOption
// The x axis option
XAxis XAxisOption
} }
func defaultRender(p *Painter, opt defaultRenderOption) *Painter { type defaultRenderResult struct {
axisRanges map[int]axisRange
p *Painter
}
func defaultRender(p *Painter, opt defaultRenderOption) (*defaultRenderResult, error) {
p.SetBackground(p.Width(), p.Height(), opt.Theme.GetBackgroundColor()) p.SetBackground(p.Width(), p.Height(), opt.Theme.GetBackgroundColor())
if !opt.Padding.IsZero() { if !opt.Padding.IsZero() {
p = p.Child(PainterPaddingOption(opt.Padding)) p = p.Child(PainterPaddingOption(opt.Padding))
} }
return p result := defaultRenderResult{
axisRanges: make(map[int]axisRange),
}
// 计算图表对应的轴有哪些
axisIndexList := make([]int, 0)
for _, series := range opt.SeriesList {
if containsInt(axisIndexList, series.AxisIndex) {
continue
}
axisIndexList = append(axisIndexList, series.index)
}
// 高度需要减去x轴的高度
rangeHeight := p.Height() - defaultXAxisHeight
rangeWidth := 0
// 计算对应的axis range
for _, index := range axisIndexList {
max, min := opt.SeriesList.GetMaxMin(index)
r := NewRange(AxisRangeOption{
Min: min,
Max: max,
// 高度需要减去x轴的高度
Size: rangeHeight,
// 分隔数量
DivideCount: defaultAxisDivideCount,
})
result.axisRanges[index] = r
yAxisOption := YAxisOption{}
if len(opt.YAxisOptions) > index {
yAxisOption = opt.YAxisOptions[index]
}
if yAxisOption.Theme == nil {
yAxisOption.Theme = opt.Theme
}
yAxisOption.Data = r.Values()
reverseStringSlice(yAxisOption.Data)
// TODO生成其它位置既yAxis
yAxis := NewLeftYAxis(p, yAxisOption)
yAxisBox, err := yAxis.Render()
if err != nil {
return nil, err
}
rangeWidth += yAxisBox.Width()
}
if opt.XAxis.Theme == nil {
opt.XAxis.Theme = opt.Theme
}
xAxis := NewBottomXAxis(p.Child(PainterPaddingOption(Box{
Left: rangeWidth,
})), opt.XAxis)
_, err := xAxis.Render()
if err != nil {
return nil, err
}
// // 生成Y轴
// for _, yAxisOption := range opt.YAxisOptions {
// }
result.p = p.Child(PainterPaddingOption(Box{
Bottom: rangeHeight,
Left: rangeWidth,
}))
return &result, nil
} }
func doRender(renderers ...Renderer) error { func doRender(renderers ...Renderer) error {

View file

@ -50,53 +50,28 @@ type LineChartOption struct {
// The padding of line chart // The padding of line chart
Padding Box Padding Box
// The y axis option // The y axis option
YAxis YAxisOption YAxisOptions []YAxisOption
} }
func (l *lineChart) Render() (Box, error) { func (l *lineChart) Render() (Box, error) {
p := l.p p := l.p
opt := l.opt opt := l.opt
p = defaultRender(p, defaultRenderOption{
Theme: opt.Theme,
Padding: opt.Padding,
})
seriesList := opt.SeriesList seriesList := opt.SeriesList
seriesList.init() seriesList.init()
// 过滤前先计算最大最小值 renderResult, err := defaultRender(p, defaultRenderOption{
max, min := seriesList.GetMaxMin() Theme: opt.Theme,
Padding: opt.Padding,
seriesList = seriesList.Filter(ChartTypeLine) SeriesList: seriesList,
XAxis: opt.XAxis,
// Y轴 YAxisOptions: opt.YAxisOptions,
yr := NewRange(AxisRangeOption{
Min: min,
Max: max,
// 高度需要减去x轴的高度
Size: p.Height() - defaultXAxisHeight,
DivideCount: defaultAxisDivideCount,
}) })
if opt.YAxis.Theme == nil {
opt.YAxis.Theme = opt.Theme
}
opt.YAxis.Data = yr.Values()
reverseStringSlice(opt.YAxis.Data)
yAxis := NewLeftYAxis(p, opt.YAxis)
yAxisBox, err := yAxis.Render()
if err != nil { if err != nil {
return chart.BoxZero, err return chart.BoxZero, err
} }
seriesPainter := p.Child(PainterPaddingOption(Box{
Bottom: defaultXAxisHeight,
Left: yAxisBox.Width(),
}))
if opt.XAxis.Theme == nil { seriesList = seriesList.Filter(ChartTypeLine)
opt.XAxis.Theme = opt.Theme
} seriesPainter := renderResult.p
xAxis := NewBottomXAxis(p.Child(PainterPaddingOption(Box{
Left: yAxisBox.Width(),
})), opt.XAxis)
xDivideValues := autoDivide(seriesPainter.Width(), len(opt.XAxis.Data)) xDivideValues := autoDivide(seriesPainter.Width(), len(opt.XAxis.Data))
xValues := make([]int, len(xDivideValues)-1) xValues := make([]int, len(xDivideValues)-1)
@ -110,6 +85,7 @@ func (l *lineChart) Render() (Box, error) {
StrokeWidth: 2, StrokeWidth: 2,
FillColor: seriesColor, FillColor: seriesColor,
}) })
yr := renderResult.axisRanges[series.AxisIndex]
points := make([]Point, 0) points := make([]Point, 0)
for i, item := range series.Data { for i, item := range series.Data {
h := yr.getRestHeight(item.Value) h := yr.getRestHeight(item.Value)
@ -123,12 +99,5 @@ func (l *lineChart) Render() (Box, error) {
seriesPainter.Dots(points) seriesPainter.Dots(points)
} }
err = doRender(
xAxis,
)
if err != nil {
return chart.BoxZero, err
}
return p.box, nil return p.box, nil
} }

View file

@ -99,8 +99,8 @@ type Series struct {
// The data list of series // The data list of series
Data []SeriesData Data []SeriesData
// The Y axis index, it should be 0 or 1. // The Y axis index, it should be 0 or 1.
// Default value is 1 // Default value is 0
YAxisIndex int AxisIndex int
// The style for series // The style for series
Style chart.Style Style chart.Style
// The label for series // The label for series
@ -143,10 +143,13 @@ func (sl SeriesList) Filter(chartType string) SeriesList {
} }
// GetMaxMin get max and min value of series list // GetMaxMin get max and min value of series list
func (sl SeriesList) GetMaxMin() (float64, float64) { func (sl SeriesList) GetMaxMin(axisIndex int) (float64, float64) {
min := math.MaxFloat64 min := math.MaxFloat64
max := -math.MaxFloat64 max := -math.MaxFloat64
for _, series := range sl { for _, series := range sl {
if series.AxisIndex != axisIndex {
continue
}
for _, item := range series.Data { for _, item := range series.Data {
if item.Value > max { if item.Value > max {
max = item.Value max = item.Value