refactor: default render function for axis
This commit is contained in:
parent
c4045cfbbe
commit
72e11e49b1
3 changed files with 97 additions and 49 deletions
80
charts.go
80
charts.go
|
|
@ -29,14 +29,90 @@ type Renderer interface {
|
|||
type defaultRenderOption struct {
|
||||
Theme ColorPalette
|
||||
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())
|
||||
if !opt.Padding.IsZero() {
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -50,53 +50,28 @@ type LineChartOption struct {
|
|||
// The padding of line chart
|
||||
Padding Box
|
||||
// The y axis option
|
||||
YAxis YAxisOption
|
||||
YAxisOptions []YAxisOption
|
||||
}
|
||||
|
||||
func (l *lineChart) Render() (Box, error) {
|
||||
p := l.p
|
||||
opt := l.opt
|
||||
p = defaultRender(p, defaultRenderOption{
|
||||
Theme: opt.Theme,
|
||||
Padding: opt.Padding,
|
||||
})
|
||||
|
||||
seriesList := opt.SeriesList
|
||||
seriesList.init()
|
||||
// 过滤前先计算最大最小值
|
||||
max, min := seriesList.GetMaxMin()
|
||||
|
||||
seriesList = seriesList.Filter(ChartTypeLine)
|
||||
|
||||
// Y轴
|
||||
yr := NewRange(AxisRangeOption{
|
||||
Min: min,
|
||||
Max: max,
|
||||
// 高度需要减去x轴的高度
|
||||
Size: p.Height() - defaultXAxisHeight,
|
||||
DivideCount: defaultAxisDivideCount,
|
||||
renderResult, err := defaultRender(p, defaultRenderOption{
|
||||
Theme: opt.Theme,
|
||||
Padding: opt.Padding,
|
||||
SeriesList: seriesList,
|
||||
XAxis: opt.XAxis,
|
||||
YAxisOptions: opt.YAxisOptions,
|
||||
})
|
||||
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 {
|
||||
return chart.BoxZero, err
|
||||
}
|
||||
seriesPainter := p.Child(PainterPaddingOption(Box{
|
||||
Bottom: defaultXAxisHeight,
|
||||
Left: yAxisBox.Width(),
|
||||
}))
|
||||
|
||||
if opt.XAxis.Theme == nil {
|
||||
opt.XAxis.Theme = opt.Theme
|
||||
}
|
||||
xAxis := NewBottomXAxis(p.Child(PainterPaddingOption(Box{
|
||||
Left: yAxisBox.Width(),
|
||||
})), opt.XAxis)
|
||||
seriesList = seriesList.Filter(ChartTypeLine)
|
||||
|
||||
seriesPainter := renderResult.p
|
||||
|
||||
xDivideValues := autoDivide(seriesPainter.Width(), len(opt.XAxis.Data))
|
||||
xValues := make([]int, len(xDivideValues)-1)
|
||||
|
|
@ -110,6 +85,7 @@ func (l *lineChart) Render() (Box, error) {
|
|||
StrokeWidth: 2,
|
||||
FillColor: seriesColor,
|
||||
})
|
||||
yr := renderResult.axisRanges[series.AxisIndex]
|
||||
points := make([]Point, 0)
|
||||
for i, item := range series.Data {
|
||||
h := yr.getRestHeight(item.Value)
|
||||
|
|
@ -123,12 +99,5 @@ func (l *lineChart) Render() (Box, error) {
|
|||
seriesPainter.Dots(points)
|
||||
}
|
||||
|
||||
err = doRender(
|
||||
xAxis,
|
||||
)
|
||||
if err != nil {
|
||||
return chart.BoxZero, err
|
||||
}
|
||||
|
||||
return p.box, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,8 +99,8 @@ type Series struct {
|
|||
// The data list of series
|
||||
Data []SeriesData
|
||||
// The Y axis index, it should be 0 or 1.
|
||||
// Default value is 1
|
||||
YAxisIndex int
|
||||
// Default value is 0
|
||||
AxisIndex int
|
||||
// The style for series
|
||||
Style chart.Style
|
||||
// The label for series
|
||||
|
|
@ -143,10 +143,13 @@ func (sl SeriesList) Filter(chartType string) SeriesList {
|
|||
}
|
||||
|
||||
// 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
|
||||
max := -math.MaxFloat64
|
||||
for _, series := range sl {
|
||||
if series.AxisIndex != axisIndex {
|
||||
continue
|
||||
}
|
||||
for _, item := range series.Data {
|
||||
if item.Value > max {
|
||||
max = item.Value
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue