refactor: add examples of chart

This commit is contained in:
vicanso 2022-02-12 11:22:08 +08:00
parent e558634dda
commit 4262b148ca
10 changed files with 796 additions and 100 deletions

View file

@ -37,7 +37,6 @@ func barChartRender(opt ChartOption, result *basicRenderResult) ([]*markPointRen
if err != nil { if err != nil {
return nil, err return nil, err
} }
// yRange := result.yRange
xRange := result.xRange xRange := result.xRange
x0, x1 := xRange.GetRange(0) x0, x1 := xRange.GetRange(0)
width := int(x1 - x0) width := int(x1 - x0)
@ -45,6 +44,10 @@ func barChartRender(opt ChartOption, result *basicRenderResult) ([]*markPointRen
margin := 10 margin := 10
// 每一个bar之间的margin // 每一个bar之间的margin
barMargin := 5 barMargin := 5
if width < 50 {
margin = 5
barMargin = 3
}
seriesCount := len(opt.SeriesList) seriesCount := len(opt.SeriesList)
// 总的宽度-两个margin-(总数-1)的barMargin // 总的宽度-两个margin-(总数-1)的barMargin
@ -80,9 +83,9 @@ func barChartRender(opt ChartOption, result *basicRenderResult) ([]*markPointRen
Series: &series, Series: &series,
Range: yRange, Range: yRange,
}) })
divideValues := xRange.AutoDivide()
for j, item := range series.Data { for j, item := range series.Data {
x0, _ := xRange.GetRange(j) x := divideValues[j]
x := int(x0)
x += margin x += margin
if i != 0 { if i != 0 {
x += i * (barWidth + barMargin) x += i * (barWidth + barMargin)

View file

@ -144,18 +144,25 @@ func (o *ChartOption) FillDefault(theme string) {
} }
func (o *ChartOption) getWidth() int { func (o *ChartOption) getWidth() int {
if o.Width == 0 { if o.Width != 0 {
return 600
}
return o.Width return o.Width
} }
if o.Parent != nil {
return o.Parent.Box.Width()
}
return 600
}
func (o *ChartOption) getHeight() int { func (o *ChartOption) getHeight() int {
if o.Height == 0 {
return 400 if o.Height != 0 {
}
return o.Height return o.Height
} }
if o.Parent != nil {
return o.Parent.Box.Height()
}
return 400
}
func (o *ChartOption) newYRange(axisIndex int) Range { func (o *ChartOption) newYRange(axisIndex int) Range {
min := math.MaxFloat64 min := math.MaxFloat64
@ -219,6 +226,7 @@ func Render(opt ChartOption) (*Draw, error) {
if len(opt.SeriesList) == 0 { if len(opt.SeriesList) == 0 {
return nil, errors.New("series can not be nil") return nil, errors.New("series can not be nil")
} }
opt.FillDefault(opt.Theme)
lineSeries := make([]Series, 0) lineSeries := make([]Series, 0)
barSeries := make([]Series, 0) barSeries := make([]Series, 0)
@ -321,7 +329,6 @@ func Render(opt ChartOption) (*Draw, error) {
} }
func chartBasicRender(opt *ChartOption) (*basicRenderResult, error) { func chartBasicRender(opt *ChartOption) (*basicRenderResult, error) {
opt.FillDefault(opt.Theme)
d, err := NewDraw( d, err := NewDraw(
DrawOption{ DrawOption{
Type: opt.Type, Type: opt.Type,

View file

@ -6,6 +6,7 @@ import (
charts "github.com/vicanso/go-charts" charts "github.com/vicanso/go-charts"
"github.com/wcharczuk/go-chart/v2" "github.com/wcharczuk/go-chart/v2"
"github.com/wcharczuk/go-chart/v2/drawing"
) )
var html = `<!DOCTYPE html> var html = `<!DOCTYPE html>
@ -13,7 +14,6 @@ var html = `<!DOCTYPE html>
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favicon.ico" />
<link type="text/css" rel="styleSheet" href="https://unpkg.com/normalize.css@8.0.1/normalize.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style> <style>
body { body {
@ -49,7 +49,7 @@ var html = `<!DOCTYPE html>
display: block; display: block;
} }
svg{ svg{
margin: auto auto 50px auto; margin: auto auto 10px auto;
display: block; display: block;
} }
</style> </style>
@ -61,20 +61,565 @@ var html = `<!DOCTYPE html>
</html> </html>
` `
func indexHandler(w http.ResponseWriter, r *http.Request) { func indexHandler(w http.ResponseWriter, req *http.Request) {
if req.URL.Path != "/" {
return
}
theme := req.URL.Query().Get("theme")
chartOptions := []charts.ChartOption{
// 普通折线图
{
Theme: theme,
Title: charts.TitleOption{
Text: "Line",
},
Legend: charts.NewLegendOption([]string{
"Email",
"Union Ads",
"Video Ads",
"Direct",
"Search Engine",
}),
XAxis: charts.NewXAxisOption([]string{
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat",
"Sun",
}),
SeriesList: []charts.Series{
charts.NewSeriesFromValues([]float64{
120,
132,
101,
134,
90,
230,
210,
}),
charts.NewSeriesFromValues([]float64{
220,
182,
191,
234,
290,
330,
310,
}),
charts.NewSeriesFromValues([]float64{
150,
232,
201,
154,
190,
330,
410,
}),
charts.NewSeriesFromValues([]float64{
320,
332,
301,
334,
390,
330,
320,
}),
charts.NewSeriesFromValues([]float64{
820,
932,
901,
934,
1290,
1330,
1320,
}),
},
},
// 温度折线图
{
Theme: theme,
Title: charts.TitleOption{
Text: "Temperature Change in the Coming Week",
},
Padding: chart.Box{
Top: 20,
Left: 20,
Right: 30,
Bottom: 20,
},
Legend: charts.NewLegendOption([]string{
"Highest",
"Lowest",
}, charts.PositionRight),
XAxis: charts.NewXAxisOption([]string{
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat",
"Sun",
}, charts.FalseFlag()),
SeriesList: []charts.Series{
{
Data: charts.NewSeriesDataFromValues([]float64{
14,
11,
13,
11,
12,
12,
7,
}),
MarkPoint: charts.NewMarkPoint(charts.SeriesMarkDataTypeMax, charts.SeriesMarkDataTypeMin),
MarkLine: charts.NewMarkLine(charts.SeriesMarkDataTypeAverage),
},
{
Data: charts.NewSeriesDataFromValues([]float64{
1,
-2,
2,
5,
3,
2,
0,
}),
MarkLine: charts.NewMarkLine(charts.SeriesMarkDataTypeAverage),
},
},
},
// 柱状图
{
Theme: theme,
Title: charts.TitleOption{
Text: "Bar",
},
XAxis: charts.NewXAxisOption([]string{
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat",
"Sun",
}),
Legend: charts.NewLegendOption([]string{
"Rainfall",
"Evaporation",
}),
SeriesList: []charts.Series{
charts.NewSeriesFromValues([]float64{
120,
200,
150,
80,
70,
110,
130,
}, charts.ChartTypeBar),
{
Type: charts.ChartTypeBar,
Data: []charts.SeriesData{
{
Value: 100,
},
{
Value: 190,
Style: chart.Style{
FillColor: drawing.Color{
R: 169,
G: 0,
B: 0,
A: 255,
},
},
},
{
Value: 230,
},
{
Value: 140,
},
{
Value: 100,
},
{
Value: 200,
},
{
Value: 180,
},
},
},
},
},
// 柱状图+mark
{
Theme: theme,
Title: charts.TitleOption{
Text: "Rainfall vs Evaporation",
Subtext: "Fake Data",
},
Padding: chart.Box{
Top: 20,
Right: 20,
Bottom: 20,
Left: 20,
},
XAxis: charts.NewXAxisOption([]string{
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
}),
Legend: charts.NewLegendOption([]string{
"Rainfall",
"Evaporation",
}, charts.PositionRight),
SeriesList: []charts.Series{
{
Type: charts.ChartTypeBar,
Data: charts.NewSeriesDataFromValues([]float64{
2.0,
4.9,
7.0,
23.2,
25.6,
76.7,
135.6,
162.2,
32.6,
20.0,
6.4,
3.3,
}),
MarkPoint: charts.NewMarkPoint(
charts.SeriesMarkDataTypeMax,
charts.SeriesMarkDataTypeMin,
),
MarkLine: charts.NewMarkLine(
charts.SeriesMarkDataTypeAverage,
),
},
{
Type: charts.ChartTypeBar,
Data: charts.NewSeriesDataFromValues([]float64{
2.6,
5.9,
9.0,
26.4,
28.7,
70.7,
175.6,
182.2,
48.7,
18.8,
6.0,
2.3,
}),
MarkPoint: charts.NewMarkPoint(
charts.SeriesMarkDataTypeMax,
charts.SeriesMarkDataTypeMin,
),
MarkLine: charts.NewMarkLine(
charts.SeriesMarkDataTypeAverage,
),
},
},
},
// 双Y轴示例
{
Theme: theme,
XAxis: charts.NewXAxisOption([]string{
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
}),
Legend: charts.NewLegendOption([]string{
"Evaporation",
"Precipitation",
"Temperature",
}),
YAxisList: []charts.YAxisOption{
{
Formatter: "{value}°C",
Color: drawing.Color{
R: 250,
G: 200,
B: 88,
A: 255,
},
},
{
Formatter: "{value}ml",
Color: drawing.Color{
R: 84,
G: 112,
B: 198,
A: 255,
},
},
},
SeriesList: []charts.Series{
{
Type: charts.ChartTypeBar,
Data: charts.NewSeriesDataFromValues([]float64{
2.0,
4.9,
7.0,
23.2,
25.6,
76.7,
135.6,
162.2,
32.6,
20.0,
6.4,
3.3,
}),
YAxisIndex: 1,
},
{
Type: charts.ChartTypeBar,
Data: charts.NewSeriesDataFromValues([]float64{
2.6,
5.9,
9.0,
26.4,
28.7,
70.7,
175.6,
182.2,
48.7,
18.8,
6.0,
2.3,
}),
YAxisIndex: 1,
},
{
Data: charts.NewSeriesDataFromValues([]float64{
2.0,
2.2,
3.3,
4.5,
6.3,
10.2,
20.3,
23.4,
23.0,
16.5,
12.0,
6.2,
}),
},
},
},
// 饼图
{
Theme: theme,
Title: charts.TitleOption{
Text: "Referer of a Website",
Subtext: "Fake Data",
Left: charts.PositionCenter,
},
Legend: charts.LegendOption{
Orient: charts.OrientVertical,
Data: []string{
"Search Engine",
"Direct",
"Email",
"Union Ads",
"Video Ads",
},
Left: charts.PositionLeft,
},
SeriesList: charts.NewPieSeriesList([]float64{
1048,
735,
580,
484,
300,
}, charts.PieSeriesOption{
LabelShow: true,
Radius: "35%",
}),
},
// 多图展示
{
Theme: theme,
Legend: charts.LegendOption{
Top: "-90",
Data: []string{
"Milk Tea",
"Matcha Latte",
"Cheese Cocoa",
"Walnut Brownie",
},
},
Padding: chart.Box{
Top: 100,
},
XAxis: charts.NewXAxisOption([]string{
"2012",
"2013",
"2014",
"2015",
"2016",
"2017",
}),
YAxisList: []charts.YAxisOption{
{
Min: charts.NewFloatPoint(0),
Max: charts.NewFloatPoint(90),
},
},
SeriesList: []charts.Series{
charts.NewSeriesFromValues([]float64{
56.5,
82.1,
88.7,
70.1,
53.4,
85.1,
}),
charts.NewSeriesFromValues([]float64{
51.1,
51.4,
55.1,
53.3,
73.8,
68.7,
}),
charts.NewSeriesFromValues([]float64{
40.1,
62.2,
69.5,
36.4,
45.2,
32.5,
}, charts.ChartTypeBar),
charts.NewSeriesFromValues([]float64{
25.2,
37.1,
41.2,
18,
33.9,
49.1,
}, charts.ChartTypeBar),
},
Children: []charts.ChartOption{
{
Legend: charts.LegendOption{
Show: charts.FalseFlag(),
Data: []string{
"Milk Tea",
"Matcha Latte",
"Cheese Cocoa",
"Walnut Brownie",
},
},
Height: 20,
Padding: chart.Box{
Left: 250,
Top: -80,
},
SeriesList: charts.NewPieSeriesList([]float64{
435.9,
354.3,
285.9,
204.5,
}, charts.PieSeriesOption{
LabelShow: true,
Radius: "35%",
}),
},
},
},
}
bytesList := make([][]byte, 0)
for _, opt := range chartOptions {
d, err := charts.Render(opt)
if err != nil {
panic(err)
}
buf, err := d.Bytes()
if err != nil {
panic(err)
}
bytesList = append(bytesList, buf)
}
data := bytes.ReplaceAll([]byte(html), []byte("{{body}}"), bytes.Join(bytesList, []byte("")))
w.Header().Set("Content-Type", "text/html")
w.Write(data)
}
func indexHandlerBak(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" { if r.URL.Path != "/" {
return return
} }
d, err := charts.NewLineChart(charts.LineChartOption{ zero := float64(0)
ChartOption: charts.ChartOption{ outputType := r.URL.Query().Get("type")
Theme: "dark", chartOption := charts.ChartOption{
// Theme: "dark",
Type: outputType,
Title: charts.TitleOption{
Left: charts.PositionCenter,
Style: chart.Style{
FontColor: chart.ColorAlternateBlue,
},
SubtextStyle: chart.Style{
FontColor: chart.ColorRed,
},
Text: "Stacked Line",
Subtext: "Hello World!",
},
Padding: chart.Box{ Padding: chart.Box{
Left: 5, Left: 5,
Top: 15, Top: 15,
Bottom: 5, Bottom: 5,
Right: 10, Right: 10,
}, },
YAxisList: []charts.YAxisOption{
{
Min: &zero,
},
{
Formatter: "{value} °C",
// Max: charts.NewFloatPoint(24),
},
},
Legend: charts.LegendOption{
Data: []string{
"Email",
"Union Ads",
// "Video Ads",
},
Left: charts.PositionLeft,
// Orient: charts.OrientVertical,
},
XAxis: charts.XAxisOption{ XAxis: charts.XAxisOption{
Data: []string{ Data: []string{
"Mon", "Mon",
@ -85,97 +630,165 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
"Sat", "Sat",
"Sun", "Sun",
}, },
// SplitNumber: 4,
// BoundaryGap: charts.FalseFlag(), // BoundaryGap: charts.FalseFlag(),
}, },
SeriesList: []charts.Series{ SeriesList: []charts.Series{
{ {
Data: []charts.SeriesData{ // Type: charts.ChartTypeBar,
MarkPoint: charts.SeriesMarkPoint{
Data: []charts.SeriesMarkPointData{
{ {
Value: 150, Type: "max",
}, },
{ {
Value: 230, Type: "min",
}, },
},
},
MarkLine: charts.SeriesMarkLine{
Data: []charts.SeriesMarkLineData{
// {
// Type: "max",
// },
{ {
Value: 224, Type: "average",
}, },
},
},
Data: charts.NewSeriesDataFromValues([]float64{
2.0,
4.9,
7.0,
23.2,
25.6,
76.7,
135.6,
}),
},
// {
// // Type: charts.ChartTypeBar,
// Data: charts.NewSeriesDataFromValues([]float64{
// 2.6,
// 5.9,
// 9.0,
// 26.4,
// 28.7,
// 70.7,
// 175.6,
// }),
// },
{ {
Value: 218, Data: charts.NewSeriesDataFromValues([]float64{
2.0,
2.2,
3.3,
4.5,
6.3,
10.2,
20.3,
}),
YAxisIndex: 1,
}, },
{ // {
Value: 135, // Data: []charts.SeriesData{
// {
// Value: 220,
// },
// {
// Value: 182,
// },
// {
// Value: 191,
// },
// {
// Value: 234,
// },
// {
// Value: 290,
// },
// {
// Value: 330,
// },
// {
// Value: 310,
// },
// },
// },
// {
// Data: []charts.SeriesData{
// {
// Value: 150,
// },
// {
// Value: 232,
// },
// {
// Value: 201,
// },
// {
// Value: 154,
// },
// {
// Value: 190,
// },
// {
// Value: 330,
// },
// {
// Value: 410,
// },
// },
// },
}, },
{ // Children: []charts.ChartOption{
Value: 147, // {
}, // Padding: chart.Box{
{ // Left: 350,
Value: 260, // Top: 0,
}, // },
}, // Legend: charts.LegendOption{
}, // Show: charts.FalseFlag(),
{ // },
Data: []charts.SeriesData{ // Width: 150,
{ // Height: 150,
Value: 220, // SeriesList: []charts.Series{
}, // charts.NewSeriesFromValues([]float64{
{ // 1048,
Value: 182, // }, charts.ChartTypePie),
}, // {
{ // Data: charts.NewSeriesDataFromValues([]float64{
Value: 191, // 735,
}, // }),
{ // Radius: "50%",
Value: 234, // Name: "test",
}, // },
{ // charts.NewSeriesFromValues([]float64{
Value: 290, // 580,
}, // }),
{ // charts.NewSeriesFromValues([]float64{
Value: 330, // 484,
}, // }),
{ // },
Value: 310, // },
}, // },
}, }
}, d, err := charts.Render(chartOption)
{
Data: []charts.SeriesData{
{
Value: 150,
},
{
Value: 232,
},
{
Value: 201,
},
{
Value: 154,
},
{
Value: 190,
},
{
Value: 330,
},
{
Value: 410,
},
},
},
},
},
})
if err != nil { if err != nil {
panic(err) panic(err)
} }
buf, _ := d.Bytes() buf, _ := d.Bytes()
if outputType == "png" {
w.Header().Set("Content-Type", "image/png")
w.Write(buf)
} else {
data := bytes.ReplaceAll([]byte(html), []byte("{{body}}"), buf) data := bytes.ReplaceAll([]byte(html), []byte("{{body}}"), buf)
w.Header().Set("Content-Type", "text/html") w.Header().Set("Content-Type", "text/html")
w.Write(data) w.Write(data)
} }
}
func main() { func main() {
http.HandleFunc("/", indexHandler) http.HandleFunc("/", indexHandler)

View file

@ -49,6 +49,17 @@ type LegendOption struct {
// The layout orientation of legend, it can be horizontal or vertical, default is horizontal. // The layout orientation of legend, it can be horizontal or vertical, default is horizontal.
Orient string Orient string
} }
func NewLegendOption(data []string, position ...string) LegendOption {
opt := LegendOption{
Data: data,
}
if len(position) != 0 {
opt.Left = position[0]
}
return opt
}
type legend struct { type legend struct {
d *Draw d *Draw
opt *LegendOption opt *LegendOption

View file

@ -38,7 +38,6 @@ func getPieStyle(theme *Theme, index int) chart.Style {
StrokeWidth: 1, StrokeWidth: 1,
FillColor: seriesColor, FillColor: seriesColor,
} }
} }
func pieChartRender(opt ChartOption, result *basicRenderResult) error { func pieChartRender(opt ChartOption, result *basicRenderResult) error {
@ -86,7 +85,11 @@ func pieChartRender(opt ChartOption, result *basicRenderResult) error {
if radius <= 0 { if radius <= 0 {
radius = float64(diameter) * defaultRadiusPercent radius = float64(diameter) * defaultRadiusPercent
} }
labelRadius := radius + 20 labelLineWidth := 15
if radius < 50 {
labelLineWidth = 10
}
labelRadius := radius + float64(labelLineWidth)
seriesNames := opt.Legend.Data seriesNames := opt.Legend.Data
@ -126,7 +129,7 @@ func pieChartRender(opt ChartOption, result *basicRenderResult) error {
endy := cy + int(labelRadius*math.Sin(angle)) endy := cy + int(labelRadius*math.Sin(angle))
d.moveTo(startx, starty) d.moveTo(startx, starty)
d.lineTo(endx, endy) d.lineTo(endx, endy)
offset := 30 offset := labelLineWidth
if endx < cx { if endx < cx {
offset *= -1 offset *= -1
} }

View file

@ -94,6 +94,9 @@ func (r *Range) GetRange(index int) (float64, float64) {
unit := float64(r.Size) / float64(r.divideCount) unit := float64(r.Size) / float64(r.divideCount)
return unit * float64(index), unit * float64(index+1) return unit * float64(index), unit * float64(index+1)
} }
func (r *Range) AutoDivide() []int {
return autoDivide(r.Size, r.divideCount)
}
func (r *Range) getWidth(value float64) int { func (r *Range) getWidth(value float64) int {
v := value / (r.Max - r.Min) v := value / (r.Max - r.Min)

View file

@ -95,6 +95,35 @@ type Series struct {
MarkLine SeriesMarkLine MarkLine SeriesMarkLine
} }
type PieSeriesOption struct {
Radius string
LabelShow bool
}
func NewPieSeriesList(values []float64, opts ...PieSeriesOption) []Series {
result := make([]Series, len(values))
var opt PieSeriesOption
if len(opts) != 0 {
opt = opts[0]
}
for index, v := range values {
s := Series{
Type: ChartTypePie,
Data: []SeriesData{
{
Value: v,
},
},
Radius: opt.Radius,
Label: SeriesLabel{
Show: opt.LabelShow,
},
}
result[index] = s
}
return result
}
type seriesSummary struct { type seriesSummary struct {
MaxIndex int MaxIndex int
MaxValue float64 MaxValue float64

View file

@ -40,6 +40,14 @@ func FalseFlag() *bool {
return &f return &f
} }
func ceilFloatToInt(value float64) int {
i := int(value)
if value == float64(i) {
return i
}
return i + 1
}
func getDefaultInt(value, defaultValue int) int { func getDefaultInt(value, defaultValue int) int {
if value == 0 { if value == 0 {
return defaultValue return defaultValue

View file

@ -40,6 +40,16 @@ type XAxisOption struct {
SplitNumber int SplitNumber int
} }
func NewXAxisOption(data []string, boundaryGap ...*bool) XAxisOption {
opt := XAxisOption{
Data: data,
}
if len(boundaryGap) != 0 {
opt.BoundaryGap = boundaryGap[0]
}
return opt
}
// drawXAxis draws x axis, and returns the height, range of if. // drawXAxis draws x axis, and returns the height, range of if.
func drawXAxis(p *Draw, opt *XAxisOption, yAxisCount int) (int, *Range, error) { func drawXAxis(p *Draw, opt *XAxisOption, yAxisCount int) (int, *Range, error) {
if opt.Hidden { if opt.Hidden {

View file

@ -26,6 +26,7 @@ import (
"strings" "strings"
"github.com/wcharczuk/go-chart/v2" "github.com/wcharczuk/go-chart/v2"
"github.com/wcharczuk/go-chart/v2/drawing"
) )
type YAxisOption struct { type YAxisOption struct {
@ -37,15 +38,19 @@ type YAxisOption struct {
Hidden bool Hidden bool
// Formatter for y axis text value // Formatter for y axis text value
Formatter string Formatter string
// Color for y axis
Color drawing.Color
} }
// TODO 长度是否可以变化
const YAxisWidth = 40 const YAxisWidth = 40
func drawYAxis(p *Draw, opt *ChartOption, axisIndex, xAxisHeight int, padding chart.Box) (*Range, error) { func drawYAxis(p *Draw, opt *ChartOption, axisIndex, xAxisHeight int, padding chart.Box) (*Range, error) {
theme := NewTheme(opt.Theme) theme := NewTheme(opt.Theme)
yRange := opt.newYRange(axisIndex) yRange := opt.newYRange(axisIndex)
values := yRange.Values() values := yRange.Values()
formatter := opt.YAxisList[axisIndex].Formatter yAxis := opt.YAxisList[axisIndex]
formatter := yAxis.Formatter
if len(formatter) != 0 { if len(formatter) != 0 {
for index, text := range values { for index, text := range values {
values[index] = strings.ReplaceAll(formatter, "{value}", text) values[index] = strings.ReplaceAll(formatter, "{value}", text)
@ -62,6 +67,10 @@ func drawYAxis(p *Draw, opt *ChartOption, axisIndex, xAxisHeight int, padding ch
SplitLineColor: theme.GetAxisSplitLineColor(), SplitLineColor: theme.GetAxisSplitLineColor(),
SplitLineShow: true, SplitLineShow: true,
} }
if !yAxis.Color.IsZero() {
style.FontColor = yAxis.Color
style.StrokeColor = yAxis.Color
}
width := NewAxis(p, data, style).measure().Width width := NewAxis(p, data, style).measure().Width
yAxisCount := len(opt.YAxisList) yAxisCount := len(opt.YAxisList)