feat: support label for line chart, #23

This commit is contained in:
vicanso 2022-09-22 20:10:45 +08:00
parent 825e65d930
commit de49ef8c68
3 changed files with 89 additions and 14 deletions

View file

@ -62,13 +62,6 @@ type BarChartOption struct {
Legend LegendOption Legend LegendOption
} }
type barChartLabelRenderOption struct {
Text string
Style Style
X int
Y int
}
func (b *barChart) render(result *defaultRenderResult, seriesList SeriesList) (Box, error) { func (b *barChart) render(result *defaultRenderResult, seriesList SeriesList) (Box, error) {
p := b.p p := b.p
opt := b.opt opt := b.opt
@ -100,11 +93,12 @@ func (b *barChart) render(result *defaultRenderResult, seriesList SeriesList) (B
markPointPainter := NewMarkPointPainter(seriesPainter) markPointPainter := NewMarkPointPainter(seriesPainter)
markLinePainter := NewMarkLinePainter(seriesPainter) markLinePainter := NewMarkLinePainter(seriesPainter)
labelPainter := NewSeriesLabelPainter(seriesPainter)
rendererList := []Renderer{ rendererList := []Renderer{
labelPainter,
markPointPainter, markPointPainter,
markLinePainter, markLinePainter,
} }
labelRenderOptions := make([]barChartLabelRenderOption, 0)
for index := range seriesList { for index := range seriesList {
series := seriesList[index] series := seriesList[index]
yRange := result.axisRanges[series.AxisIndex] yRange := result.axisRanges[series.AxisIndex]
@ -168,8 +162,7 @@ func (b *barChart) render(result *defaultRenderResult, seriesList SeriesList) (B
} }
textBox := seriesPainter.MeasureText(text) textBox := seriesPainter.MeasureText(text)
labelPainter.Add(LabelValue{
labelRenderOptions = append(labelRenderOptions, barChartLabelRenderOption{
Text: text, Text: text,
Style: labelStyle, Style: labelStyle,
X: x + (barWidth-textBox.Width())>>1, X: x + (barWidth-textBox.Width())>>1,
@ -192,10 +185,6 @@ func (b *barChart) render(result *defaultRenderResult, seriesList SeriesList) (B
Range: yRange, Range: yRange,
}) })
} }
for _, labelOpt := range labelRenderOptions {
seriesPainter.OverrideTextStyle(labelOpt.Style)
seriesPainter.Text(labelOpt.Text, labelOpt.X, labelOpt.Y)
}
// 最大、最小的mark point // 最大、最小的mark point
err := doRender(rendererList...) err := doRender(rendererList...)
if err != nil { if err != nil {

View file

@ -97,7 +97,9 @@ func (l *lineChart) render(result *defaultRenderResult, seriesList SeriesList) (
} }
markPointPainter := NewMarkPointPainter(seriesPainter) markPointPainter := NewMarkPointPainter(seriesPainter)
markLinePainter := NewMarkLinePainter(seriesPainter) markLinePainter := NewMarkLinePainter(seriesPainter)
labelPainter := NewSeriesLabelPainter(seriesPainter)
rendererList := []Renderer{ rendererList := []Renderer{
labelPainter,
markPointPainter, markPointPainter,
markLinePainter, markLinePainter,
} }
@ -105,6 +107,8 @@ func (l *lineChart) render(result *defaultRenderResult, seriesList SeriesList) (
if strokeWidth == 0 { if strokeWidth == 0 {
strokeWidth = defaultStrokeWidth strokeWidth = defaultStrokeWidth
} }
seriesNames := seriesList.Names()
theme := opt.Theme
for index := range seriesList { for index := range seriesList {
series := seriesList[index] series := seriesList[index]
seriesColor := opt.Theme.GetSeriesColor(series.index) seriesColor := opt.Theme.GetSeriesColor(series.index)
@ -125,6 +129,32 @@ func (l *lineChart) render(result *defaultRenderResult, seriesList SeriesList) (
Y: h, Y: h,
} }
points = append(points, p) points = append(points, p)
// 如果label不需要展示则返回
if !series.Label.Show {
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,
})
} }
// 如果需要填充区域 // 如果需要填充区域
if opt.FillArea { if opt.FillArea {

56
series_label.go Normal file
View file

@ -0,0 +1,56 @@
// MIT License
// Copyright (c) 2022 Tree Xie
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
package charts
import "github.com/wcharczuk/go-chart/v2"
type LabelValue struct {
Text string
Style Style
X int
Y int
}
type SeriesLabelPainter struct {
p *Painter
values []LabelValue
}
func NewSeriesLabelPainter(p *Painter) *SeriesLabelPainter {
return &SeriesLabelPainter{
p: p,
values: make([]LabelValue, 0),
}
}
func (o *SeriesLabelPainter) Add(value LabelValue) {
o.values = append(o.values, value)
}
func (o *SeriesLabelPainter) Render() (Box, error) {
for _, item := range o.values {
o.p.OverrideTextStyle(item.Style)
o.p.Text(item.Text, item.X, item.Y)
}
return chart.BoxZero, nil
}