From 1f5b9d513ee4387b2fc5a0f8a2b3ccb3836ad42f Mon Sep 17 00:00:00 2001 From: vicanso Date: Fri, 23 Sep 2022 20:50:42 +0800 Subject: [PATCH] refactor: adjust series label render --- bar_chart.go | 39 ++++++++++++--------------- bar_chart_test.go | 2 +- line_chart.go | 39 +++++++++++---------------- series_label.go | 69 ++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 94 insertions(+), 55 deletions(-) diff --git a/bar_chart.go b/bar_chart.go index 797f710..8826ffb 100644 --- a/bar_chart.go +++ b/bar_chart.go @@ -93,9 +93,7 @@ func (b *barChart) render(result *defaultRenderResult, seriesList SeriesList) (B markPointPainter := NewMarkPointPainter(seriesPainter) markLinePainter := NewMarkLinePainter(seriesPainter) - labelPainter := NewSeriesLabelPainter(seriesPainter) rendererList := []Renderer{ - labelPainter, markPointPainter, markLinePainter, } @@ -106,6 +104,18 @@ func (b *barChart) render(result *defaultRenderResult, seriesList SeriesList) (B divideValues := xRange.AutoDivide() points := make([]Point, len(series.Data)) + var labelPainter *SeriesLabelPainter + if series.Label.Show { + labelPainter = NewSeriesLabelPainter(SeriesLabelPainterParams{ + P: seriesPainter, + SeriesNames: seriesNames, + Label: series.Label, + Theme: opt.Theme, + Font: opt.Font, + }) + rendererList = append(rendererList, labelPainter) + } + for j, item := range series.Data { if j >= xRange.divideCount { continue @@ -144,29 +154,14 @@ func (b *barChart) render(result *defaultRenderResult, seriesList SeriesList) (B Y: top, } // 如果label不需要展示,则返回 - if !series.Label.Show { + if labelPainter == nil { continue } - distance := series.Label.Distance - if distance == 0 { - distance = 5 - } - text := NewValueLabelFormatter(seriesNames, series.Label.Formatter)(index, item.Value, -1) - labelStyle := Style{ - FontColor: theme.GetTextColor(), - FontSize: labelFontSize, - Font: opt.Font, - } - if !series.Label.Color.IsZero() { - labelStyle.FontColor = series.Label.Color - } - - textBox := seriesPainter.MeasureText(text) labelPainter.Add(LabelValue{ - Text: text, - Style: labelStyle, - X: x + (barWidth-textBox.Width())>>1, - Y: barMaxHeight - h - distance, + Index: index, + Value: item.Value, + X: x + barWidth>>1, + Y: barMaxHeight - h, }) } diff --git a/bar_chart_test.go b/bar_chart_test.go index bee0583..e1522d6 100644 --- a/bar_chart_test.go +++ b/bar_chart_test.go @@ -102,7 +102,7 @@ func TestBarChart(t *testing.T) { } return p.Bytes() }, - result: "\\n24020016012080400FebMayAugNov24.9723.225.676.7135.6162.232.6206.43.32.65.9926.428.770.7175.6182.248.718.862.3", + result: "\\n24020016012080400FebMayAugNov24.9723.225.676.7135.6162.232.6206.43.32.65.9926.428.770.7175.6182.248.718.862.3", }, } diff --git a/line_chart.go b/line_chart.go index bf39ae2..26f94a4 100644 --- a/line_chart.go +++ b/line_chart.go @@ -97,9 +97,7 @@ func (l *lineChart) render(result *defaultRenderResult, seriesList SeriesList) ( } markPointPainter := NewMarkPointPainter(seriesPainter) markLinePainter := NewMarkLinePainter(seriesPainter) - labelPainter := NewSeriesLabelPainter(seriesPainter) rendererList := []Renderer{ - labelPainter, markPointPainter, markLinePainter, } @@ -108,7 +106,6 @@ func (l *lineChart) render(result *defaultRenderResult, seriesList SeriesList) ( strokeWidth = defaultStrokeWidth } seriesNames := seriesList.Names() - theme := opt.Theme for index := range seriesList { series := seriesList[index] seriesColor := opt.Theme.GetSeriesColor(series.index) @@ -119,6 +116,17 @@ func (l *lineChart) render(result *defaultRenderResult, seriesList SeriesList) ( yRange := result.axisRanges[series.AxisIndex] points := make([]Point, 0) + var labelPainter *SeriesLabelPainter + if series.Label.Show { + labelPainter = NewSeriesLabelPainter(SeriesLabelPainterParams{ + P: seriesPainter, + SeriesNames: seriesNames, + Label: series.Label, + Theme: opt.Theme, + Font: opt.Font, + }) + rendererList = append(rendererList, labelPainter) + } for i, item := range series.Data { h := yRange.getRestHeight(item.Value) if item.Value == nullValue { @@ -131,29 +139,14 @@ func (l *lineChart) render(result *defaultRenderResult, seriesList SeriesList) ( points = append(points, p) // 如果label不需要展示,则返回 - if !series.Label.Show { + if labelPainter == nil { continue } - distance := series.Label.Distance - if distance == 0 { - distance = 5 - } - text := NewValueLabelFormatter(seriesNames, series.Label.Formatter)(index, item.Value, -1) - labelStyle := Style{ - FontColor: theme.GetTextColor(), - FontSize: labelFontSize, - Font: opt.Font, - } - if !series.Label.Color.IsZero() { - labelStyle.FontColor = series.Label.Color - } - - textBox := seriesPainter.MeasureText(text) labelPainter.Add(LabelValue{ - Text: text, - Style: labelStyle, - X: p.X - textBox.Width()>>1, - Y: p.Y - distance, + Index: index, + Value: item.Value, + X: p.X, + Y: p.Y, }) } // 如果需要填充区域 diff --git a/series_label.go b/series_label.go index c1850bb..57bd1bf 100644 --- a/series_label.go +++ b/series_label.go @@ -22,29 +22,80 @@ package charts -import "github.com/wcharczuk/go-chart/v2" +import ( + "github.com/golang/freetype/truetype" + "github.com/wcharczuk/go-chart/v2" +) -type LabelValue struct { +type labelRenderValue struct { Text string Style Style X int Y int } -type SeriesLabelPainter struct { - p *Painter - values []LabelValue +type LabelValue struct { + Index int + Value float64 + X int + Y int } -func NewSeriesLabelPainter(p *Painter) *SeriesLabelPainter { +type SeriesLabelPainter struct { + p *Painter + seriesNames []string + label *SeriesLabel + theme ColorPalette + font *truetype.Font + values []labelRenderValue +} + +type SeriesLabelPainterParams struct { + P *Painter + SeriesNames []string + Label SeriesLabel + Theme ColorPalette + Font *truetype.Font +} + +func NewSeriesLabelPainter(params SeriesLabelPainterParams) *SeriesLabelPainter { return &SeriesLabelPainter{ - p: p, - values: make([]LabelValue, 0), + p: params.P, + seriesNames: params.SeriesNames, + label: ¶ms.Label, + theme: params.Theme, + font: params.Font, + values: make([]labelRenderValue, 0), } } func (o *SeriesLabelPainter) Add(value LabelValue) { - o.values = append(o.values, value) + label := o.label + distance := label.Distance + if distance == 0 { + distance = 5 + } + text := NewValueLabelFormatter(o.seriesNames, label.Formatter)(value.Index, value.Value, -1) + labelStyle := Style{ + FontColor: o.theme.GetTextColor(), + FontSize: labelFontSize, + Font: o.font, + } + if !label.Color.IsZero() { + labelStyle.FontColor = label.Color + } + o.p.OverrideDrawingStyle(labelStyle) + textBox := o.p.MeasureText(text) + renderValue := labelRenderValue{ + Text: text, + Style: labelStyle, + X: value.X - textBox.Width()>>1, + Y: value.Y - distance, + } + if textBox.Width()%2 != 0 { + renderValue.X++ + } + o.values = append(o.values, renderValue) } func (o *SeriesLabelPainter) Render() (Box, error) {