refactor: enhance chart render function

This commit is contained in:
vicanso 2022-06-17 23:37:21 +08:00
parent 65a1cb11ad
commit 38c4978e44
20 changed files with 665 additions and 462 deletions

View file

@ -49,25 +49,21 @@ func writeFile(file string, buf []byte) error {
}
func chartsRender() ([]byte, error) {
d, err := charts.LineRender([][]float64{
values := [][]float64{
{
150,
120,
132,
101,
134,
90,
230,
224,
218,
135,
147,
260,
210,
},
},
// output type
charts.PNGTypeOption(),
// title
charts.TitleOptionFunc(charts.TitleOption{
Text: "Line",
}),
// x axis
charts.XAxisOptionFunc(charts.NewXAxisOption([]string{
}
p, err := charts.LineRender(
values,
charts.TitleTextOptionFunc("Line"),
charts.XAxisDataOptionFunc([]string{
"Mon",
"Tue",
"Wed",
@ -75,12 +71,12 @@ func chartsRender() ([]byte, error) {
"Fri",
"Sat",
"Sun",
})),
}),
)
if err != nil {
return nil, err
}
return d.Bytes()
return p.Bytes()
}
func echartsRender() ([]byte, error) {

View file

@ -34,7 +34,7 @@ type barChart struct {
func NewBarChart(p *Painter, opt BarChartOption) *barChart {
if opt.Theme == nil {
opt.Theme = NewTheme("")
opt.Theme = defaultTheme
}
return &barChart{
p: p,

View file

@ -66,6 +66,182 @@ type ChartOption struct {
Children []ChartOption
}
// OptionFunc option function
type OptionFunc func(opt *ChartOption)
// PNGTypeOption set png type of chart's output
func PNGTypeOption() OptionFunc {
return TypeOptionFunc(ChartOutputPNG)
}
// TypeOptionFunc set type of chart's output
func TypeOptionFunc(t string) OptionFunc {
return func(opt *ChartOption) {
opt.Type = t
}
}
// FontFamilyOptionFunc set font family of chart
func FontFamilyOptionFunc(fontFamily string) OptionFunc {
return func(opt *ChartOption) {
opt.FontFamily = fontFamily
}
}
// ThemeOptionFunc set them of chart
func ThemeOptionFunc(theme string) OptionFunc {
return func(opt *ChartOption) {
opt.Theme = theme
}
}
// TitleOptionFunc set title of chart
func TitleOptionFunc(title TitleOption) OptionFunc {
return func(opt *ChartOption) {
opt.Title = title
}
}
// TitleTextOptionFunc set title text of chart
func TitleTextOptionFunc(text string) OptionFunc {
return func(opt *ChartOption) {
opt.Title.Text = text
}
}
// LegendOptionFunc set legend of chart
func LegendOptionFunc(legend LegendOption) OptionFunc {
return func(opt *ChartOption) {
opt.Legend = legend
}
}
// LegendLabelsOptionFunc set legend labels of chart
func LegendLabelsOptionFunc(labels []string, left ...string) OptionFunc {
return func(opt *ChartOption) {
opt.Legend = NewLegendOption(labels, left...)
}
}
// XAxisOptionFunc set x axis of chart
func XAxisOptionFunc(xAxisOption XAxisOption) OptionFunc {
return func(opt *ChartOption) {
opt.XAxis = xAxisOption
}
}
// XAxisDataOptionFunc set x axis data of chart
func XAxisDataOptionFunc(data []string, boundaryGap ...*bool) OptionFunc {
return func(opt *ChartOption) {
opt.XAxis = NewXAxisOption(data, boundaryGap...)
}
}
// YAxisOptionFunc set y axis of chart, support two y axis
func YAxisOptionFunc(yAxisOption ...YAxisOption) OptionFunc {
return func(opt *ChartOption) {
opt.YAxisOptions = yAxisOption
}
}
// YAxisDataOptionFunc set y axis data of chart
func YAxisDataOptionFunc(data []string) OptionFunc {
return func(opt *ChartOption) {
opt.YAxisOptions = NewYAxisOptions(data)
}
}
// WidthOptionFunc set width of chart
func WidthOptionFunc(width int) OptionFunc {
return func(opt *ChartOption) {
opt.Width = width
}
}
// HeightOptionFunc set height of chart
func HeightOptionFunc(height int) OptionFunc {
return func(opt *ChartOption) {
opt.Height = height
}
}
// PaddingOptionFunc set padding of chart
func PaddingOptionFunc(padding Box) OptionFunc {
return func(opt *ChartOption) {
opt.Padding = padding
}
}
// BoxOptionFunc set box of chart
func BoxOptionFunc(box Box) OptionFunc {
return func(opt *ChartOption) {
opt.Box = box
}
}
// PieSeriesShowLabel set pie series show label
func PieSeriesShowLabel() OptionFunc {
return func(opt *ChartOption) {
for index := range opt.SeriesList {
opt.SeriesList[index].Label.Show = true
}
}
}
// ChildOptionFunc add child chart
func ChildOptionFunc(child ...ChartOption) OptionFunc {
return func(opt *ChartOption) {
if opt.Children == nil {
opt.Children = make([]ChartOption, 0)
}
opt.Children = append(opt.Children, child...)
}
}
// RadarIndicatorOptionFunc set radar indicator of chart
func RadarIndicatorOptionFunc(names []string, values []float64) OptionFunc {
return func(opt *ChartOption) {
if len(names) != len(values) {
return
}
indicators := make([]RadarIndicator, len(names))
for index, name := range names {
indicators[index] = RadarIndicator{
Name: name,
Max: values[index],
}
}
opt.RadarIndicators = indicators
}
}
// BackgroundColorOptionFunc set background color of chart
func BackgroundColorOptionFunc(color Color) OptionFunc {
return func(opt *ChartOption) {
opt.BackgroundColor = color
}
}
// MarkLineOptionFunc set mark line for series of chart
func MarkLineOptionFunc(seriesIndex int, markLineTypes ...string) OptionFunc {
return func(opt *ChartOption) {
if len(opt.SeriesList) <= seriesIndex {
return
}
opt.SeriesList[seriesIndex].MarkLine = NewMarkLine(markLineTypes...)
}
}
// MarkPointOptionFunc set mark point for series of chart
func MarkPointOptionFunc(seriesIndex int, markPointTypes ...string) OptionFunc {
return func(opt *ChartOption) {
if len(opt.SeriesList) <= seriesIndex {
return
}
opt.SeriesList[seriesIndex].MarkPoint = NewMarkPoint(markPointTypes...)
}
}
func (o *ChartOption) fillDefault() {
t := NewTheme(o.Theme)
o.theme = t
@ -90,11 +266,11 @@ func (o *ChartOption) fillDefault() {
o.BackgroundColor = t.GetBackgroundColor()
}
if o.Padding.IsZero() {
o.Padding = chart.Box{
Top: 10,
Right: 10,
Bottom: 10,
Left: 10,
o.Padding = Box{
Top: 20,
Right: 20,
Bottom: 20,
Left: 20,
}
}
// legend与series name的关联
@ -118,3 +294,55 @@ func (o *ChartOption) fillDefault() {
})
}
}
// LineRender line chart render
func LineRender(values [][]float64, opts ...OptionFunc) (*Painter, error) {
seriesList := NewSeriesListDataFromValues(values, ChartTypeLine)
return Render(ChartOption{
SeriesList: seriesList,
}, opts...)
}
// BarRender bar chart render
func BarRender(values [][]float64, opts ...OptionFunc) (*Painter, error) {
seriesList := NewSeriesListDataFromValues(values, ChartTypeBar)
return Render(ChartOption{
SeriesList: seriesList,
}, opts...)
}
// HorizontalBarRender horizontal bar chart render
func HorizontalBarRender(values [][]float64, opts ...OptionFunc) (*Painter, error) {
seriesList := NewSeriesListDataFromValues(values, ChartTypeHorizontalBar)
return Render(ChartOption{
SeriesList: seriesList,
}, opts...)
}
// PieRender pie chart render
func PieRender(values []float64, opts ...OptionFunc) (*Painter, error) {
return Render(ChartOption{
SeriesList: NewPieSeriesList(values),
}, opts...)
}
// RadarRender radar chart render
func RadarRender(values [][]float64, opts ...OptionFunc) (*Painter, error) {
seriesList := NewSeriesListDataFromValues(values, ChartTypeRadar)
return Render(ChartOption{
SeriesList: seriesList,
}, opts...)
}
// FunnelRender funnel chart render
func FunnelRender(values []float64, opts ...OptionFunc) (*Painter, error) {
seriesList := make(SeriesList, len(values))
for index, value := range values {
seriesList[index] = NewSeriesFromValues([]float64{
value,
}, ChartTypeFunnel)
}
return Render(ChartOption{
SeriesList: seriesList,
}, opts...)
}

View file

@ -239,7 +239,10 @@ func doRender(renderers ...Renderer) error {
return nil
}
func Render(opt ChartOption) (*Painter, error) {
func Render(opt ChartOption, opts ...OptionFunc) (*Painter, error) {
for _, fn := range opts {
fn(&opt)
}
opt.fillDefault()
isChild := true
@ -398,6 +401,12 @@ func Render(opt ChartOption) (*Painter, error) {
}
for _, item := range opt.Children {
item.Parent = p
if item.Theme == "" {
item.Theme = opt.Theme
}
if item.FontFamily == "" {
item.FontFamily = opt.FontFamily
}
_, err = Render(item)
if err != nil {
return nil, err

View file

@ -130,6 +130,7 @@ type EChartsXAxisData struct {
BoundaryGap *bool `json:"boundaryGap"`
SplitNumber int `json:"splitNumber"`
Data []string `json:"data"`
Type string `json:"type"`
}
type EChartsXAxis struct {
Data []EChartsXAxisData
@ -155,6 +156,7 @@ type EChartsYAxisData struct {
Color string `json:"color"`
} `json:"lineStyle"`
} `json:"axisLine"`
Data []string `json:"data"`
}
type EChartsYAxis struct {
Data []EChartsYAxisData `json:"data"`
@ -453,6 +455,21 @@ func (eo *EChartsOption) ToOption() ChartOption {
Box: eo.Box,
SeriesList: eo.Series.ToSeriesList(),
}
isHorizontalChart := false
for _, item := range eo.XAxis.Data {
if item.Type == "value" {
isHorizontalChart = true
}
}
if isHorizontalChart {
for index := range o.SeriesList {
series := o.SeriesList[index]
if series.Type == ChartTypeBar {
o.SeriesList[index].Type = ChartTypeHorizontalBar
}
}
}
if len(eo.XAxis.Data) != 0 {
xAxisData := eo.XAxis.Data[0]
o.XAxis = XAxisOption{
@ -468,6 +485,7 @@ func (eo *EChartsOption) ToOption() ChartOption {
Max: item.Max,
Formatter: item.AxisLabel.Formatter,
Color: parseColor(item.AxisLine.LineStyle.Color),
Data: item.Data,
}
}
o.YAxisOptions = yAxisOptions

View file

@ -24,26 +24,39 @@ func writeFile(buf []byte) error {
}
func main() {
p, err := charts.NewPainter(charts.PainterOptions{
Width: 800,
Height: 600,
Type: charts.ChartOutputPNG,
})
if err != nil {
panic(err)
values := [][]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,
},
{
2.6,
5.9,
9.0,
26.4,
28.7,
70.7,
175.6,
182.2,
48.7,
18.8,
6.0,
2.3,
},
}
_, err = charts.NewBarChart(p, charts.BarChartOption{
Title: charts.TitleOption{
Text: "Rainfall vs Evaporation",
Subtext: "Fake Data",
},
Padding: charts.Box{
Top: 20,
Right: 20,
Bottom: 20,
Left: 20,
},
XAxis: charts.NewXAxisOption([]string{
p, err := charts.BarRender(
values,
charts.XAxisDataOptionFunc([]string{
"Jan",
"Feb",
"Mar",
@ -57,61 +70,24 @@ func main() {
"Nov",
"Dec",
}),
Legend: charts.NewLegendOption([]string{
charts.LegendLabelsOptionFunc([]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,
),
},
charts.MarkLineOptionFunc(0, charts.SeriesMarkDataTypeAverage),
charts.MarkPointOptionFunc(0, charts.SeriesMarkDataTypeMax,
charts.SeriesMarkDataTypeMin),
// custom option func
func(opt *charts.ChartOption) {
opt.SeriesList[1].MarkPoint = charts.NewMarkPoint(
charts.SeriesMarkDataTypeMax,
charts.SeriesMarkDataTypeMin,
)
opt.SeriesList[1].MarkLine = charts.NewMarkLine(
charts.SeriesMarkDataTypeAverage,
)
},
}).Render()
)
if err != nil {
panic(err)
}

View file

@ -73,6 +73,7 @@ func handler(w http.ResponseWriter, req *http.Request, chartOptions []charts.Cha
bytesList := make([][]byte, 0)
for _, opt := range chartOptions {
opt.Theme = theme
opt.Type = charts.ChartOutputSVG
d, err := charts.Render(opt)
if err != nil {
panic(err)
@ -1055,6 +1056,64 @@ func echartsHandler(w http.ResponseWriter, req *http.Request) {
}
]
}`,
`{
"title": {
"text": "World Population"
},
"tooltip": {
"trigger": "axis",
"axisPointer": {
"type": "shadow"
}
},
"legend": {},
"grid": {
"left": "3%",
"right": "4%",
"bottom": "3%",
"containLabel": true
},
"xAxis": {
"type": "value"
},
"yAxis": {
"type": "category",
"data": [
"Brazil",
"Indonesia",
"USA",
"India",
"China",
"World"
]
},
"series": [
{
"name": "2011",
"type": "bar",
"data": [
18203,
23489,
29034,
104970,
131744,
630230
]
},
{
"name": "2012",
"type": "bar",
"data": [
19325,
23438,
31000,
121594,
134141,
681807
]
}
]
}`,
`{
"title": {
"text": "Rainfall vs Evaporation",

View file

@ -24,64 +24,24 @@ func writeFile(buf []byte) error {
}
func main() {
p, err := charts.NewPainter(charts.PainterOptions{
Width: 800,
Height: 600,
Type: charts.ChartOutputPNG,
})
if err != nil {
panic(err)
values := []float64{
100,
80,
60,
40,
20,
}
_, err = charts.NewFunnelChart(p, charts.FunnelChartOption{
Title: charts.TitleOption{
Text: "Funnel",
},
Legend: charts.NewLegendOption([]string{
p, err := charts.FunnelRender(
values,
charts.TitleTextOptionFunc("Funnel"),
charts.LegendLabelsOptionFunc([]string{
"Show",
"Click",
"Visit",
"Inquiry",
"Order",
}),
SeriesList: []charts.Series{
{
Type: charts.ChartTypeFunnel,
Name: "Show",
Data: charts.NewSeriesDataFromValues([]float64{
100,
}),
},
{
Type: charts.ChartTypeFunnel,
Name: "Click",
Data: charts.NewSeriesDataFromValues([]float64{
80,
}),
},
{
Type: charts.ChartTypeFunnel,
Name: "Visit",
Data: charts.NewSeriesDataFromValues([]float64{
60,
}),
},
{
Type: charts.ChartTypeFunnel,
Name: "Inquiry",
Data: charts.NewSeriesDataFromValues([]float64{
40,
}),
},
{
Type: charts.ChartTypeFunnel,
Name: "Order",
Data: charts.NewSeriesDataFromValues([]float64{
20,
}),
},
},
}).Render()
)
if err != nil {
panic(err)
}

View file

@ -24,29 +24,38 @@ func writeFile(buf []byte) error {
}
func main() {
p, err := charts.NewPainter(charts.PainterOptions{
Width: 800,
Height: 600,
Type: charts.ChartOutputPNG,
})
if err != nil {
panic(err)
}
_, err = charts.NewHorizontalBarChart(p, charts.HorizontalBarChartOption{
Title: charts.TitleOption{
Text: "World Population",
values := [][]float64{
{
18203,
23489,
29034,
104970,
131744,
630230,
},
Padding: charts.Box{
{
19325,
23438,
31000,
121594,
134141,
681807,
},
}
p, err := charts.HorizontalBarRender(
values,
charts.TitleTextOptionFunc("World Population"),
charts.PaddingOptionFunc(charts.Box{
Top: 20,
Right: 40,
Bottom: 20,
Left: 20,
},
Legend: charts.NewLegendOption([]string{
}),
charts.LegendLabelsOptionFunc([]string{
"2011",
"2012",
}),
YAxisOptions: charts.NewYAxisOptions([]string{
charts.YAxisDataOptionFunc([]string{
"Brazil",
"Indonesia",
"USA",
@ -54,31 +63,7 @@ func main() {
"China",
"World",
}),
SeriesList: []charts.Series{
{
Type: charts.ChartTypeHorizontalBar,
Data: charts.NewSeriesDataFromValues([]float64{
18203,
23489,
29034,
104970,
131744,
630230,
}),
},
{
Type: charts.ChartTypeHorizontalBar,
Data: charts.NewSeriesDataFromValues([]float64{
19325,
23438,
31000,
121594,
134141,
681807,
}),
},
},
}).Render()
)
if err != nil {
panic(err)
}

View file

@ -24,35 +24,57 @@ func writeFile(buf []byte) error {
}
func main() {
p, err := charts.NewPainter(charts.PainterOptions{
Width: 800,
Height: 600,
Type: charts.ChartOutputPNG,
})
if err != nil {
panic(err)
values := [][]float64{
{
120,
132,
101,
134,
90,
230,
210,
},
{
220,
182,
191,
234,
290,
330,
310,
},
{
150,
232,
201,
154,
190,
330,
410,
},
{
320,
332,
301,
334,
390,
330,
320,
},
{
820,
932,
901,
934,
1290,
1330,
1320,
},
}
_, err = charts.NewLineChart(p, charts.LineChartOption{
Padding: charts.Box{
Left: 10,
Top: 10,
Right: 10,
Bottom: 10,
},
Title: charts.TitleOption{
Text: "Line",
},
Legend: charts.LegendOption{
Data: []string{
"Email",
"Union Ads",
"Video Ads",
"Direct",
"Search Engine",
},
Left: charts.PositionCenter,
},
XAxis: charts.NewXAxisOption([]string{
p, err := charts.LineRender(
values,
charts.TitleTextOptionFunc("Line"),
charts.XAxisDataOptionFunc([]string{
"Mon",
"Tue",
"Wed",
@ -61,54 +83,15 @@ func main() {
"Sat",
"Sun",
}),
SeriesList: charts.SeriesList{
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,
}),
},
}).Render()
charts.LegendLabelsOptionFunc([]string{
"Email",
"Union Ads",
"Video Ads",
"Direct",
"Search Engine",
}, charts.PositionCenter),
)
if err != nil {
panic(err)
}

View file

@ -24,27 +24,27 @@ func writeFile(buf []byte) error {
}
func main() {
p, err := charts.NewPainter(charts.PainterOptions{
Width: 800,
Height: 600,
Type: charts.ChartOutputPNG,
})
if err != nil {
panic(err)
values := []float64{
1048,
735,
580,
484,
300,
}
_, err = charts.NewPieChart(p, charts.PieChartOption{
Title: charts.TitleOption{
p, err := charts.PieRender(
values,
charts.TitleOptionFunc(charts.TitleOption{
Text: "Rainfall vs Evaporation",
Subtext: "Fake Data",
Left: charts.PositionCenter,
},
Padding: charts.Box{
}),
charts.PaddingOptionFunc(charts.Box{
Top: 20,
Right: 20,
Bottom: 20,
Left: 20,
},
Legend: charts.LegendOption{
}),
charts.LegendOptionFunc(charts.LegendOption{
Orient: charts.OrientVertical,
Data: []string{
"Search Engine",
@ -54,20 +54,9 @@ func main() {
"Video Ads",
},
Left: charts.PositionLeft,
},
SeriesList: charts.NewPieSeriesList([]float64{
1048,
735,
580,
484,
300,
}, charts.PieSeriesOption{
Label: charts.SeriesLabel{
Show: true,
},
Radius: "35%",
}),
}).Render()
charts.PieSeriesShowLabel(),
)
if err != nil {
panic(err)
}

View file

@ -24,79 +24,47 @@ func writeFile(buf []byte) error {
}
func main() {
p, err := charts.NewPainter(charts.PainterOptions{
Width: 800,
Height: 600,
Type: charts.ChartOutputPNG,
})
if err != nil {
panic(err)
values := [][]float64{
{
4200,
3000,
20000,
35000,
50000,
18000,
},
{
5000,
14000,
28000,
26000,
42000,
21000,
},
}
_, err = charts.NewRadarChart(p, charts.RadarChartOption{
Padding: charts.Box{
Left: 10,
Top: 10,
Right: 10,
Bottom: 10,
},
Title: charts.TitleOption{
Text: "Basic Radar Chart",
},
Legend: charts.NewLegendOption([]string{
p, err := charts.RadarRender(
values,
charts.TitleTextOptionFunc("Basic Radar Chart"),
charts.LegendLabelsOptionFunc([]string{
"Allocated Budget",
"Actual Spending",
}),
RadarIndicators: []charts.RadarIndicator{
{
Name: "Sales",
Max: 6500,
},
{
Name: "Administration",
Max: 16000,
},
{
Name: "Information Technology",
Max: 30000,
},
{
Name: "Customer Support",
Max: 38000,
},
{
Name: "Development",
Max: 52000,
},
{
Name: "Marketing",
Max: 25000,
},
},
SeriesList: charts.SeriesList{
{
Type: charts.ChartTypeRadar,
Data: charts.NewSeriesDataFromValues([]float64{
4200,
3000,
20000,
35000,
50000,
18000,
}),
},
{
Type: charts.ChartTypeRadar,
Data: charts.NewSeriesDataFromValues([]float64{
5000,
14000,
28000,
26000,
42000,
21000,
}),
},
},
}).Render()
charts.RadarIndicatorOptionFunc([]string{
"Sales",
"Administration",
"Information Technology",
"Customer Support",
"Development",
"Marketing",
}, []float64{
6500,
16000,
30000,
38000,
52000,
25000,
}),
)
if err != nil {
panic(err)
}

View file

@ -36,7 +36,7 @@ type funnelChart struct {
func NewFunnelChart(p *Painter, opt FunnelChartOption) *funnelChart {
if opt.Theme == nil {
opt.Theme = NewTheme("")
opt.Theme = defaultTheme
}
return &funnelChart{
p: p,

View file

@ -52,7 +52,7 @@ type HorizontalBarChartOption struct {
func NewHorizontalBarChart(p *Painter, opt HorizontalBarChartOption) *horizontalBarChart {
if opt.Theme == nil {
opt.Theme = NewTheme("")
opt.Theme = defaultTheme
}
return &horizontalBarChart{
p: p,

View file

@ -34,7 +34,7 @@ type lineChart struct {
func NewLineChart(p *Painter, opt LineChartOption) *lineChart {
if opt.Theme == nil {
opt.Theme = NewTheme("")
opt.Theme = defaultTheme
}
return &lineChart{
p: p,

View file

@ -149,9 +149,9 @@ func NewPainter(opts PainterOptions, opt ...PainterOption) (*Painter, error) {
}
font = f
}
fn := chart.SVG
if opts.Type == ChartOutputPNG {
fn = chart.PNG
fn := chart.PNG
if opts.Type == ChartOutputSVG {
fn = chart.SVG
}
width := opts.Width
height := opts.Height

View file

@ -53,7 +53,7 @@ type PieChartOption struct {
func NewPieChart(p *Painter, opt PieChartOption) *pieChart {
if opt.Theme == nil {
opt.Theme = NewTheme("")
opt.Theme = defaultTheme
}
return &pieChart{
p: p,

View file

@ -64,7 +64,7 @@ type RadarChartOption struct {
func NewRadarChart(p *Painter, opt RadarChartOption) *radarChart {
if opt.Theme == nil {
opt.Theme = NewTheme("")
opt.Theme = defaultTheme
}
return &radarChart{
p: p,

View file

@ -36,6 +36,14 @@ type SeriesData struct {
Style Style
}
func NewSeriesListDataFromValues(values [][]float64, chartType ...string) SeriesList {
seriesList := make(SeriesList, len(values))
for index, value := range values {
seriesList[index] = NewSeriesFromValues(value, chartType...)
}
return seriesList
}
func NewSeriesFromValues(values []float64, chartType ...string) Series {
s := Series{
Data: NewSeriesDataFromValues(values),

218
theme.go
View file

@ -55,10 +55,21 @@ type themeColorPalette struct {
font *truetype.Font
}
type ThemeOption struct {
IsDarkMode bool
AxisStrokeColor Color
AxisSplitLineColor Color
BackgroundColor Color
TextColor Color
SeriesColors []Color
}
var palettes = map[string]ColorPalette{}
const defaultFontSize = 12.0
var defaultTheme ColorPalette
func init() {
echartSeriesColors := []Color{
parseColor("#5470c6"),
@ -93,121 +104,134 @@ func init() {
}
AddTheme(
ThemeDark,
true,
Color{
R: 185,
G: 184,
B: 206,
A: 255,
ThemeOption{
IsDarkMode: true,
AxisStrokeColor: Color{
R: 185,
G: 184,
B: 206,
A: 255,
},
AxisSplitLineColor: Color{
R: 72,
G: 71,
B: 83,
A: 255,
},
BackgroundColor: Color{
R: 16,
G: 12,
B: 42,
A: 255,
},
TextColor: Color{
R: 238,
G: 238,
B: 238,
A: 255,
},
SeriesColors: echartSeriesColors,
},
Color{
R: 72,
G: 71,
B: 83,
A: 255,
},
Color{
R: 16,
G: 12,
B: 42,
A: 255,
},
Color{
R: 238,
G: 238,
B: 238,
A: 255,
},
echartSeriesColors,
)
AddTheme(
ThemeLight,
false,
Color{
R: 110,
G: 112,
B: 121,
A: 255,
ThemeOption{
IsDarkMode: false,
AxisStrokeColor: Color{
R: 110,
G: 112,
B: 121,
A: 255,
},
AxisSplitLineColor: Color{
R: 224,
G: 230,
B: 242,
A: 255,
},
BackgroundColor: drawing.ColorWhite,
TextColor: Color{
R: 70,
G: 70,
B: 70,
A: 255,
},
SeriesColors: echartSeriesColors,
},
Color{
R: 224,
G: 230,
B: 242,
A: 255,
},
drawing.ColorWhite,
drawing.Color{
R: 70,
G: 70,
B: 70,
A: 255,
},
echartSeriesColors,
)
AddTheme(
ThemeAnt,
false,
Color{
R: 110,
G: 112,
B: 121,
A: 255,
ThemeOption{
IsDarkMode: false,
AxisStrokeColor: Color{
R: 110,
G: 112,
B: 121,
A: 255,
},
AxisSplitLineColor: Color{
R: 224,
G: 230,
B: 242,
A: 255,
},
BackgroundColor: drawing.ColorWhite,
TextColor: drawing.Color{
R: 70,
G: 70,
B: 70,
A: 255,
},
SeriesColors: antSeriesColors,
},
Color{
R: 224,
G: 230,
B: 242,
A: 255,
},
drawing.ColorWhite,
drawing.Color{
R: 70,
G: 70,
B: 70,
A: 255,
},
antSeriesColors,
)
AddTheme(
ThemeGrafana,
true,
drawing.Color{
R: 185,
G: 184,
B: 206,
A: 255,
ThemeOption{
IsDarkMode: true,
AxisStrokeColor: Color{
R: 185,
G: 184,
B: 206,
A: 255,
},
AxisSplitLineColor: Color{
R: 68,
G: 67,
B: 67,
A: 255,
},
BackgroundColor: drawing.Color{
R: 31,
G: 29,
B: 29,
A: 255,
},
TextColor: Color{
R: 216,
G: 217,
B: 218,
A: 255,
},
SeriesColors: grafanaSeriesColors,
},
drawing.Color{
R: 68,
G: 67,
B: 67,
A: 255,
},
drawing.Color{
R: 31,
G: 29,
B: 29,
A: 255,
},
drawing.Color{
R: 216,
G: 217,
B: 218,
A: 255,
},
grafanaSeriesColors,
)
SetDefaultTheme(ThemeLight)
}
func AddTheme(name string, isDarkMode bool, axisStrokeColor, axisSplitLineColor, backgroundColor, textColor drawing.Color, seriesColors []drawing.Color) {
func SetDefaultTheme(name string) {
defaultTheme = NewTheme(name)
}
func AddTheme(name string, opt ThemeOption) {
palettes[name] = &themeColorPalette{
isDarkMode: isDarkMode,
axisStrokeColor: axisStrokeColor,
axisSplitLineColor: axisSplitLineColor,
backgroundColor: backgroundColor,
textColor: textColor,
seriesColors: seriesColors,
isDarkMode: opt.IsDarkMode,
axisStrokeColor: opt.AxisStrokeColor,
axisSplitLineColor: opt.AxisSplitLineColor,
backgroundColor: opt.BackgroundColor,
textColor: opt.TextColor,
seriesColors: opt.SeriesColors,
}
}