feat: support rotate series label

This commit is contained in:
vicanso 2022-11-22 22:41:56 +08:00
parent 55eca7b0b9
commit 4fc250aefc
5 changed files with 66 additions and 12 deletions

View file

@ -23,6 +23,8 @@
package charts package charts
import ( import (
"math"
"github.com/golang/freetype/truetype" "github.com/golang/freetype/truetype"
"github.com/wcharczuk/go-chart/v2" "github.com/wcharczuk/go-chart/v2"
) )
@ -164,11 +166,26 @@ func (b *barChart) render(result *defaultRenderResult, seriesList SeriesList) (B
if labelPainter == nil { if labelPainter == nil {
continue continue
} }
y := barMaxHeight - h
radians := float64(0)
var fontColor Color
if series.Label.Position == PositionBottom {
y = barMaxHeight
radians = -math.Pi / 2
if isLightColor(fillColor) {
fontColor = defaultLightFontColor
} else {
fontColor = defaultDarkFontColor
}
}
labelPainter.Add(LabelValue{ labelPainter.Add(LabelValue{
Index: index, Index: index,
Value: item.Value, Value: item.Value,
X: x + barWidth>>1, X: x + barWidth>>1,
Y: barMaxHeight - h, Y: y,
// 旋转
Radians: radians,
FontColor: fontColor,
}) })
} }

View file

@ -355,6 +355,10 @@ func indexHandler(w http.ResponseWriter, req *http.Request) {
Value: 180, Value: 180,
}, },
}, },
Label: charts.SeriesLabel{
Show: true,
Position: charts.PositionBottom,
},
}, },
}, },
}, },

View file

@ -560,7 +560,14 @@ func (p *Painter) Text(body string, x, y int) *Painter {
func (p *Painter) TextRotation(body string, x, y int, radians float64) { func (p *Painter) TextRotation(body string, x, y int, radians float64) {
p.render.SetTextRotation(radians) p.render.SetTextRotation(radians)
p.render.Text(body, x, y) p.render.Text(body, x+p.box.Left, y+p.box.Top)
p.render.ClearTextRotation()
}
func (p *Painter) SetTextRotation(radians float64) {
p.render.SetTextRotation(radians)
}
func (p *Painter) ClearTextRotation() {
p.render.ClearTextRotation() p.render.ClearTextRotation()
} }

View file

@ -79,6 +79,8 @@ type SeriesLabel struct {
Show bool Show bool
// Distance to the host graphic element. // Distance to the host graphic element.
Distance int Distance int
// The position of label
Position string
} }
const ( const (

View file

@ -32,6 +32,8 @@ type labelRenderValue struct {
Style Style Style Style
X int X int
Y int Y int
// 旋转
Radians float64
} }
type LabelValue struct { type LabelValue struct {
@ -39,6 +41,10 @@ type LabelValue struct {
Value float64 Value float64
X int X int
Y int Y int
// 旋转
Radians float64
// 字体颜色
FontColor Color
} }
type SeriesLabelPainter struct { type SeriesLabelPainter struct {
@ -81,19 +87,33 @@ func (o *SeriesLabelPainter) Add(value LabelValue) {
FontSize: labelFontSize, FontSize: labelFontSize,
Font: o.font, Font: o.font,
} }
if !value.FontColor.IsZero() {
label.Color = value.FontColor
}
if !label.Color.IsZero() { if !label.Color.IsZero() {
labelStyle.FontColor = label.Color labelStyle.FontColor = label.Color
} }
o.p.OverrideDrawingStyle(labelStyle) p := o.p
textBox := o.p.MeasureText(text) p.OverrideDrawingStyle(labelStyle)
renderValue := labelRenderValue{ rotated := value.Radians != 0
Text: text, if rotated {
Style: labelStyle, p.SetTextRotation(value.Radians)
X: value.X - textBox.Width()>>1,
Y: value.Y - distance,
} }
if textBox.Width()%2 != 0 { textBox := p.MeasureText(text)
renderValue.X++ renderValue := labelRenderValue{
Text: text,
Style: labelStyle,
X: value.X - textBox.Width()>>1,
Y: value.Y - distance,
Radians: value.Radians,
}
if rotated {
renderValue.X = value.X + textBox.Width()>>1 - 1
p.ClearTextRotation()
} else {
if textBox.Width()%2 != 0 {
renderValue.X++
}
} }
o.values = append(o.values, renderValue) o.values = append(o.values, renderValue)
} }
@ -101,7 +121,11 @@ func (o *SeriesLabelPainter) Add(value LabelValue) {
func (o *SeriesLabelPainter) Render() (Box, error) { func (o *SeriesLabelPainter) Render() (Box, error) {
for _, item := range o.values { for _, item := range o.values {
o.p.OverrideTextStyle(item.Style) o.p.OverrideTextStyle(item.Style)
o.p.Text(item.Text, item.X, item.Y) if item.Radians != 0 {
o.p.TextRotation(item.Text, item.X, item.Y, item.Radians)
} else {
o.p.Text(item.Text, item.X, item.Y)
}
} }
return chart.BoxZero, nil return chart.BoxZero, nil
} }