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 {
|
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 {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue