feat: support subtext for title
This commit is contained in:
parent
dfba1ceafc
commit
126244ba52
5 changed files with 81 additions and 30 deletions
6
axis.go
6
axis.go
|
|
@ -256,7 +256,7 @@ func (a *axis) axisTick(opt *axisOption) {
|
||||||
}
|
}
|
||||||
labelMargin := style.GetLabelMargin()
|
labelMargin := style.GetLabelMargin()
|
||||||
tickShow := true
|
tickShow := true
|
||||||
if style.TickShow != nil && !*style.TickShow {
|
if isFalse(style.TickShow) {
|
||||||
tickShow = false
|
tickShow = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -364,7 +364,7 @@ func (a *axis) measureAxis() int {
|
||||||
|
|
||||||
func (a *axis) Render() {
|
func (a *axis) Render() {
|
||||||
style := a.style
|
style := a.style
|
||||||
if style.Show != nil && !*style.Show {
|
if isFalse(style.Show) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
textMaxWidth, textMaxHeight := a.axisMeasureTextMaxWidthHeight()
|
textMaxWidth, textMaxHeight := a.axisMeasureTextMaxWidthHeight()
|
||||||
|
|
@ -373,7 +373,7 @@ func (a *axis) Render() {
|
||||||
textMaxHeight: textMaxHeight,
|
textMaxHeight: textMaxHeight,
|
||||||
boundaryGap: true,
|
boundaryGap: true,
|
||||||
}
|
}
|
||||||
if style.BoundaryGap != nil && !*style.BoundaryGap {
|
if isFalse(style.BoundaryGap) {
|
||||||
opt.boundaryGap = false
|
opt.boundaryGap = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
24
chart.go
24
chart.go
|
|
@ -72,11 +72,14 @@ type ChartOption struct {
|
||||||
|
|
||||||
func (o *ChartOption) FillDefault(theme string) {
|
func (o *ChartOption) FillDefault(theme string) {
|
||||||
t := NewTheme(theme)
|
t := NewTheme(theme)
|
||||||
f, _ := chart.GetDefaultFont()
|
if o.Font == nil {
|
||||||
o.Font = f
|
o.Font, _ = chart.GetDefaultFont()
|
||||||
|
}
|
||||||
if o.BackgroundColor.IsZero() {
|
if o.BackgroundColor.IsZero() {
|
||||||
o.BackgroundColor = t.GetBackgroundColor()
|
o.BackgroundColor = t.GetBackgroundColor()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 标题的默认值
|
||||||
if o.Title.Style.FontColor.IsZero() {
|
if o.Title.Style.FontColor.IsZero() {
|
||||||
o.Title.Style.FontColor = t.GetTextColor()
|
o.Title.Style.FontColor = t.GetTextColor()
|
||||||
}
|
}
|
||||||
|
|
@ -84,7 +87,7 @@ func (o *ChartOption) FillDefault(theme string) {
|
||||||
o.Title.Style.FontSize = 14
|
o.Title.Style.FontSize = 14
|
||||||
}
|
}
|
||||||
if o.Title.Style.Font == nil {
|
if o.Title.Style.Font == nil {
|
||||||
o.Title.Style.Font = f
|
o.Title.Style.Font = o.Font
|
||||||
}
|
}
|
||||||
if o.Title.Style.Padding.IsZero() {
|
if o.Title.Style.Padding.IsZero() {
|
||||||
o.Title.Style.Padding = chart.Box{
|
o.Title.Style.Padding = chart.Box{
|
||||||
|
|
@ -94,12 +97,23 @@ func (o *ChartOption) FillDefault(theme string) {
|
||||||
Bottom: 5,
|
Bottom: 5,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 副标题
|
||||||
|
if o.Title.SubtextStyle.FontColor.IsZero() {
|
||||||
|
o.Title.SubtextStyle.FontColor = o.Title.Style.FontColor.WithAlpha(180)
|
||||||
|
}
|
||||||
|
if o.Title.SubtextStyle.FontSize == 0 {
|
||||||
|
o.Title.SubtextStyle.FontSize = 10
|
||||||
|
}
|
||||||
|
if o.Title.SubtextStyle.Font == nil {
|
||||||
|
o.Title.SubtextStyle.Font = o.Font
|
||||||
|
}
|
||||||
|
|
||||||
o.Legend.Theme = t
|
o.Legend.Theme = t
|
||||||
if o.Legend.Style.FontSize == 0 {
|
if o.Legend.Style.FontSize == 0 {
|
||||||
o.Legend.Style.FontSize =10
|
o.Legend.Style.FontSize = 10
|
||||||
}
|
}
|
||||||
if o.Legend.Style.Font == nil {
|
if o.Legend.Style.Font == nil {
|
||||||
o.Legend.Style.Font = f
|
o.Legend.Style.Font = o.Font
|
||||||
}
|
}
|
||||||
if o.Legend.Style.FontColor.IsZero() {
|
if o.Legend.Style.FontColor.IsZero() {
|
||||||
o.Legend.Style.FontColor = t.GetTextColor()
|
o.Legend.Style.FontColor = t.GetTextColor()
|
||||||
|
|
|
||||||
72
title.go
72
title.go
|
|
@ -30,39 +30,71 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type TitleOption struct {
|
type TitleOption struct {
|
||||||
Text string
|
Text string
|
||||||
Style chart.Style
|
Subtext string
|
||||||
Left string
|
Style chart.Style
|
||||||
Top string
|
SubtextStyle chart.Style
|
||||||
|
Left string
|
||||||
|
Top string
|
||||||
}
|
}
|
||||||
type titleMeasureOption struct {
|
type titleMeasureOption struct {
|
||||||
width int
|
width int
|
||||||
height int
|
height int
|
||||||
text string
|
text string
|
||||||
|
style chart.Style
|
||||||
}
|
}
|
||||||
|
|
||||||
func drawTitle(d *Draw, opt *TitleOption) (chart.Box, error) {
|
func splitTitleText(text string) []string {
|
||||||
|
arr := strings.Split(text, "\n")
|
||||||
|
result := make([]string, 0)
|
||||||
|
for _, v := range arr {
|
||||||
|
v = strings.TrimSpace(v)
|
||||||
|
if v == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
result = append(result, v)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func drawTitle(p *Draw, opt *TitleOption) (chart.Box, error) {
|
||||||
if len(opt.Text) == 0 {
|
if len(opt.Text) == 0 {
|
||||||
return chart.BoxZero, nil
|
return chart.BoxZero, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
padding := opt.Style.Padding
|
padding := opt.Style.Padding
|
||||||
titleDraw, err := NewDraw(DrawOption{
|
d, err := NewDraw(DrawOption{
|
||||||
Parent: d,
|
Parent: p,
|
||||||
}, PaddingOption(padding))
|
}, PaddingOption(padding))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return chart.BoxZero, err
|
return chart.BoxZero, err
|
||||||
}
|
}
|
||||||
|
|
||||||
r := titleDraw.Render
|
r := d.Render
|
||||||
opt.Style.GetTextOptions().WriteToRenderer(r)
|
|
||||||
arr := strings.Split(opt.Text, "\n")
|
measureOptions := make([]titleMeasureOption, 0)
|
||||||
|
|
||||||
|
// 主标题
|
||||||
|
for _, v := range splitTitleText(opt.Text) {
|
||||||
|
measureOptions = append(measureOptions, titleMeasureOption{
|
||||||
|
text: v,
|
||||||
|
style: opt.Style.GetTextOptions(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 副标题
|
||||||
|
for _, v := range splitTitleText(opt.Subtext) {
|
||||||
|
measureOptions = append(measureOptions, titleMeasureOption{
|
||||||
|
text: v,
|
||||||
|
style: opt.SubtextStyle.GetTextOptions(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
textMaxWidth := 0
|
textMaxWidth := 0
|
||||||
textMaxHeight := 0
|
textMaxHeight := 0
|
||||||
width := 0
|
width := 0
|
||||||
measureOptions := make([]titleMeasureOption, len(arr))
|
for index, item := range measureOptions {
|
||||||
for index, str := range arr {
|
item.style.WriteTextOptionsToRenderer(r)
|
||||||
textBox := r.MeasureText(str)
|
textBox := r.MeasureText(item.text)
|
||||||
|
|
||||||
w := textBox.Width()
|
w := textBox.Width()
|
||||||
h := textBox.Height()
|
h := textBox.Height()
|
||||||
|
|
@ -72,15 +104,12 @@ func drawTitle(d *Draw, opt *TitleOption) (chart.Box, error) {
|
||||||
if h > textMaxHeight {
|
if h > textMaxHeight {
|
||||||
textMaxHeight = h
|
textMaxHeight = h
|
||||||
}
|
}
|
||||||
measureOptions[index] = titleMeasureOption{
|
measureOptions[index].height = h
|
||||||
text: str,
|
measureOptions[index].width = w
|
||||||
width: w,
|
|
||||||
height: h,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
width = textMaxWidth
|
width = textMaxWidth
|
||||||
titleX := 0
|
titleX := 0
|
||||||
b := titleDraw.Box
|
b := d.Box
|
||||||
switch opt.Left {
|
switch opt.Left {
|
||||||
case PositionRight:
|
case PositionRight:
|
||||||
titleX = b.Width() - textMaxWidth
|
titleX = b.Width() - textMaxWidth
|
||||||
|
|
@ -102,9 +131,10 @@ func drawTitle(d *Draw, opt *TitleOption) (chart.Box, error) {
|
||||||
titleY += value
|
titleY += value
|
||||||
}
|
}
|
||||||
for _, item := range measureOptions {
|
for _, item := range measureOptions {
|
||||||
|
item.style.WriteTextOptionsToRenderer(r)
|
||||||
x := titleX + (textMaxWidth-item.width)>>1
|
x := titleX + (textMaxWidth-item.width)>>1
|
||||||
titleDraw.text(item.text, x, titleY)
|
d.text(item.text, x, titleY)
|
||||||
titleY += textMaxHeight
|
titleY += item.height
|
||||||
}
|
}
|
||||||
height := titleY + padding.Top + padding.Bottom
|
height := titleY + padding.Top + padding.Bottom
|
||||||
box := padding.Clone()
|
box := padding.Clone()
|
||||||
|
|
|
||||||
7
util.go
7
util.go
|
|
@ -106,3 +106,10 @@ func convertPercent(value string) float64 {
|
||||||
}
|
}
|
||||||
return float64(v) / 100
|
return float64(v) / 100
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isFalse(flag *bool) bool {
|
||||||
|
if flag != nil && !*flag {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
||||||
2
xaxis.go
2
xaxis.go
|
|
@ -56,7 +56,7 @@ func drawXAxis(p *Draw, opt *XAxisOption) (int, *Range, error) {
|
||||||
|
|
||||||
boundary := true
|
boundary := true
|
||||||
max := float64(len(opt.Data))
|
max := float64(len(opt.Data))
|
||||||
if opt.BoundaryGap != nil && !*opt.BoundaryGap {
|
if isFalse(opt.BoundaryGap) {
|
||||||
boundary = false
|
boundary = false
|
||||||
max--
|
max--
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue