feat: support label for line chart, #23
This commit is contained in:
parent
825e65d930
commit
de49ef8c68
3 changed files with 89 additions and 14 deletions
17
bar_chart.go
17
bar_chart.go
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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
56
series_label.go
Normal 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
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue