test: add test for legend, series and theme

This commit is contained in:
vicanso 2021-12-23 23:20:20 +08:00
parent a128a2513c
commit c289ba7cde
11 changed files with 828 additions and 43 deletions

View file

@ -112,12 +112,15 @@ func (ep *EChartsPadding) UnmarshalJSON(data []byte) error {
default: default:
result := make([]int, 4) result := make([]int, 4)
copy(result, arr) copy(result, arr)
if len(arr) == 3 {
result[3] = result[1]
}
// 上右下左 // 上右下左
ep.box = chart.Box{ ep.box = chart.Box{
Top: arr[0], Top: result[0],
Right: arr[1], Right: result[1],
Bottom: arr[2], Bottom: result[2],
Left: arr[3], Left: result[3],
} }
} }
return nil return nil

381
echarts_test.go Normal file
View file

@ -0,0 +1,381 @@
// MIT License
// Copyright (c) 2021 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 (
"encoding/json"
"testing"
"github.com/stretchr/testify/assert"
"github.com/wcharczuk/go-chart/v2"
)
func TestConvertToArray(t *testing.T) {
assert := assert.New(t)
assert.Nil(convertToArray([]byte(" ")))
assert.Equal([]byte("[{}]"), convertToArray([]byte("{}")))
assert.Equal([]byte("[{}]"), convertToArray([]byte("[{}]")))
}
func TestECharsSeriesData(t *testing.T) {
assert := assert.New(t)
es := ECharsSeriesData{}
err := es.UnmarshalJSON([]byte(" "))
assert.Nil(err)
assert.Equal(ECharsSeriesData{}, es)
es = ECharsSeriesData{}
err = es.UnmarshalJSON([]byte("12.1"))
assert.Nil(err)
assert.Equal(ECharsSeriesData{
Value: 12.1,
}, es)
es = ECharsSeriesData{}
err = es.UnmarshalJSON([]byte(`{
"value": 12.1,
"name": "test",
"itemStyle": {
"color": "#333"
}
}`))
assert.Nil(err)
assert.Equal(ECharsSeriesData{
Value: 12.1,
Name: "test",
ItemStyle: EChartStyle{
Color: "#333",
},
}, es)
}
func TestEChartsPadding(t *testing.T) {
assert := assert.New(t)
ep := EChartsPadding{}
err := ep.UnmarshalJSON([]byte(" "))
assert.Nil(err)
assert.Equal(EChartsPadding{}, ep)
ep = EChartsPadding{}
err = ep.UnmarshalJSON([]byte("1"))
assert.Nil(err)
assert.Equal(EChartsPadding{
box: chart.Box{
Top: 1,
Left: 1,
Right: 1,
Bottom: 1,
},
}, ep)
ep = EChartsPadding{}
err = ep.UnmarshalJSON([]byte("[1, 2]"))
assert.Nil(err)
assert.Equal(EChartsPadding{
box: chart.Box{
Top: 1,
Left: 2,
Right: 2,
Bottom: 1,
},
}, ep)
ep = EChartsPadding{}
err = ep.UnmarshalJSON([]byte("[1, 2, 3]"))
assert.Nil(err)
assert.Equal(EChartsPadding{
box: chart.Box{
Top: 1,
Right: 2,
Bottom: 3,
Left: 2,
},
}, ep)
ep = EChartsPadding{}
err = ep.UnmarshalJSON([]byte("[1, 2, 3, 4]"))
assert.Nil(err)
assert.Equal(EChartsPadding{
box: chart.Box{
Top: 1,
Right: 2,
Bottom: 3,
Left: 4,
},
}, ep)
}
func TestConvertEChartsSeries(t *testing.T) {
assert := assert.New(t)
seriesList, tickPosition := convertEChartsSeries(&ECharsOptions{})
assert.Empty(seriesList)
assert.Equal(chart.TickPositionUnset, tickPosition)
e := ECharsOptions{}
err := json.Unmarshal([]byte(`{
"title": {
"text": "Referer of a Website"
},
"series": [
{
"name": "Access From",
"type": "pie",
"radius": "50%",
"data": [
{
"value": 1048,
"name": "Search Engine"
},
{
"value": 735,
"name": "Direct"
}
]
}
]
}`), &e)
assert.Nil(err)
seriesList, tickPosition = convertEChartsSeries(&e)
assert.Equal(chart.TickPositionUnset, tickPosition)
assert.Equal([]Series{
{
Data: []SeriesData{
{
Value: 1048,
},
},
Type: SeriesPie,
Name: "Search Engine",
},
{
Data: []SeriesData{
{
Value: 735,
},
},
Type: SeriesPie,
Name: "Direct",
},
}, seriesList)
err = json.Unmarshal([]byte(`{
"series": [
{
"name": "Evaporation",
"type": "bar",
"data": [2, {
"value": 4.9,
"itemStyle": {
"color": "#a90000"
}
}, 7, 23.2, 25.6, 76.7, 135.6]
},
{
"name": "Precipitation",
"type": "bar",
"data": [2.6, 5.9, 9, 26.4, 28.7, 70.7, 175.6]
},
{
"name": "Temperature",
"type": "line",
"yAxisIndex": 1,
"data": [2, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3]
}
]
}`), &e)
assert.Nil(err)
bar1Data := NewSeriesDataListFromFloat([]float64{
2, 4.9, 7, 23.2, 25.6, 76.7, 135.6,
})
bar1Data[1].Style.FillColor = parseColor("#a90000")
bar1Data[1].Style.StrokeColor = bar1Data[1].Style.FillColor
seriesList, tickPosition = convertEChartsSeries(&e)
assert.Equal(chart.TickPositionBetweenTicks, tickPosition)
assert.Equal([]Series{
{
Data: bar1Data,
Type: SeriesBar,
},
{
Data: NewSeriesDataListFromFloat([]float64{
2.6, 5.9, 9, 26.4, 28.7, 70.7, 175.6,
}),
Type: SeriesBar,
},
{
Data: NewSeriesDataListFromFloat([]float64{
2, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3,
}),
Type: SeriesLine,
YAxisIndex: 1,
},
}, seriesList)
}
func TestParseECharsOptions(t *testing.T) {
assert := assert.New(t)
options, err := ParseECharsOptions(`{
"theme": "dark",
"padding": [5, 10],
"title": {
"text": "Multi Line",
"textAlign": "left",
"textStyle": {
"color": "#333",
"fontSize": 24,
"height": 40
}
},
"legend": {
"align": "left",
"padding": [5, 0, 0, 50],
"data": ["Email", "Union Ads", "Video Ads", "Direct", "Search Engine"]
},
"xAxis": {
"type": "category",
"data": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
"splitNumber": 10
},
"yAxis": [
{
"min": 0,
"max": 250
},
{
"min": 0,
"max": 25
}
],
"series": [
{
"name": "Evaporation",
"type": "bar",
"data": [2, {
"value": 4.9,
"itemStyle": {
"color": "#a90000"
}
}, 7, 23.2, 25.6, 76.7, 135.6]
},
{
"name": "Precipitation",
"type": "bar",
"data": [2.6, 5.9, 9, 26.4, 28.7, 70.7, 175.6]
},
{
"name": "Temperature",
"type": "line",
"yAxisIndex": 1,
"data": [2, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3]
}
]
}`)
assert.Nil(err)
min1 := float64(0)
max1 := float64(250)
min2 := float64(0)
max2 := float64(25)
bar1Data := NewSeriesDataListFromFloat([]float64{
2, 4.9, 7, 23.2, 25.6, 76.7, 135.6,
})
bar1Data[1].Style.FillColor = parseColor("#a90000")
bar1Data[1].Style.StrokeColor = bar1Data[1].Style.FillColor
assert.Equal(Options{
Theme: ThemeDark,
Padding: chart.Box{
Top: 5,
Bottom: 5,
Left: 10,
Right: 10,
},
Title: Title{
Text: "Multi Line",
Style: chart.Style{
FontColor: parseColor("#333"),
FontSize: 24,
Padding: chart.Box{
Top: 8,
Bottom: 8,
},
},
},
Legend: Legend{
Data: []string{
"Email", "Union Ads", "Video Ads", "Direct", "Search Engine",
},
Align: "left",
Padding: chart.Box{
Top: 5,
Right: 0,
Bottom: 0,
Left: 50,
},
},
XAxis: XAxis{
Data: []string{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"},
SplitNumber: 10,
},
TickPosition: chart.TickPositionBetweenTicks,
YAxisOptions: []*YAxisOption{
{
Min: &min1,
Max: &max1,
},
{
Min: &min2,
Max: &max2,
},
},
Series: []Series{
{
Data: bar1Data,
Type: SeriesBar,
},
{
Data: NewSeriesDataListFromFloat([]float64{
2.6, 5.9, 9, 26.4, 28.7, 70.7, 175.6,
}),
Type: SeriesBar,
},
{
Data: NewSeriesDataListFromFloat([]float64{
2, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3,
}),
Type: SeriesLine,
YAxisIndex: 1,
},
},
}, options)
}

View file

@ -87,6 +87,7 @@ func LegendCustomize(series []chart.Series, opt LegendOption) chart.Renderable {
var labels []string var labels []string
var lines []chart.Style var lines []chart.Style
// 计算label和lines
for _, s := range series { for _, s := range series {
if !s.GetStyle().Hidden { if !s.GetStyle().Hidden {
if _, isAnnotationSeries := s.(chart.AnnotationSeries); !isAnnotationSeries { if _, isAnnotationSeries := s.(chart.AnnotationSeries); !isAnnotationSeries {
@ -100,6 +101,7 @@ func LegendCustomize(series []chart.Series, opt LegendOption) chart.Renderable {
var textWidth int var textWidth int
var textBox chart.Box var textBox chart.Box
labelWidth := 0 labelWidth := 0
// 计算文本宽度与高度(取最大值)
for x := 0; x < len(labels); x++ { for x := 0; x < len(labels); x++ {
if len(labels[x]) > 0 { if len(labels[x]) > 0 {
textBox = r.MeasureText(labels[x]) textBox = r.MeasureText(labels[x])

View file

@ -41,10 +41,26 @@ func TestLegendCustomize(t *testing.T) {
Name: "edge", Name: "edge",
}, },
}, chart.TickPositionBetweenTicks, "") }, chart.TickPositionBetweenTicks, "")
tests := []struct {
textPosition string
svg string
}{
{
textPosition: LegendTextPositionRight,
svg: "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"800\" height=\"600\">\\n<path d=\"M 100 100\nL 208 100\nL 208 110\nL 100 110\nL 100 100\" style=\"stroke-width:0;stroke:rgba(51,51,51,1.0);fill:none\"/><path d=\"M 100 107\nL 125 107\" style=\"stroke-width:2;stroke:rgba(84,112,198,1.0);fill:none\"/><circle cx=\"112\" cy=\"107\" r=\"5\" style=\"stroke-width:2;stroke:rgba(84,112,198,1.0);fill:rgba(255,255,255,1.0)\"/><path d=\"\" style=\"stroke-width:2;stroke:rgba(84,112,198,1.0);fill:rgba(255,255,255,1.0)\"/><text x=\"130\" y=\"110\" style=\"stroke-width:0;stroke:none;fill:rgba(51,51,51,1.0);font-size:10.2px;font-family:'Roboto Medium',sans-serif\">chrome</text><path d=\"M 185 107\nL 210 107\" style=\"stroke-width:2;stroke:rgba(145,204,117,1.0);fill:rgba(255,255,255,1.0)\"/><circle cx=\"197\" cy=\"107\" r=\"5\" style=\"stroke-width:2;stroke:rgba(145,204,117,1.0);fill:rgba(255,255,255,1.0)\"/><path d=\"\" style=\"stroke-width:2;stroke:rgba(145,204,117,1.0);fill:rgba(255,255,255,1.0)\"/><text x=\"215\" y=\"110\" style=\"stroke-width:0;stroke:none;fill:rgba(51,51,51,1.0);font-size:10.2px;font-family:'Roboto Medium',sans-serif\">edge</text></svg>",
},
{
textPosition: LegendAlignLeft,
svg: "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"800\" height=\"600\">\\n<path d=\"M 100 100\nL 208 100\nL 208 110\nL 100 110\nL 100 100\" style=\"stroke-width:0;stroke:rgba(51,51,51,1.0);fill:none\"/><text x=\"100\" y=\"110\" style=\"stroke-width:0;stroke:none;fill:rgba(51,51,51,1.0);font-size:10.2px;font-family:'Roboto Medium',sans-serif\">chrome</text><path d=\"M 140 107\nL 165 107\" style=\"stroke-width:2;stroke:rgba(84,112,198,1.0);fill:none\"/><circle cx=\"152\" cy=\"107\" r=\"5\" style=\"stroke-width:2;stroke:rgba(84,112,198,1.0);fill:rgba(255,255,255,1.0)\"/><path d=\"\" style=\"stroke-width:2;stroke:rgba(84,112,198,1.0);fill:rgba(255,255,255,1.0)\"/><text x=\"185\" y=\"110\" style=\"stroke-width:0;stroke:none;fill:rgba(51,51,51,1.0);font-size:10.2px;font-family:'Roboto Medium',sans-serif\">edge</text><path d=\"M 213 107\nL 238 107\" style=\"stroke-width:2;stroke:rgba(145,204,117,1.0);fill:rgba(255,255,255,1.0)\"/><circle cx=\"225\" cy=\"107\" r=\"5\" style=\"stroke-width:2;stroke:rgba(145,204,117,1.0);fill:rgba(255,255,255,1.0)\"/><path d=\"\" style=\"stroke-width:2;stroke:rgba(145,204,117,1.0);fill:rgba(255,255,255,1.0)\"/></svg>",
},
}
for _, tt := range tests {
r, err := chart.SVG(800, 600) r, err := chart.SVG(800, 600)
assert.Nil(err) assert.Nil(err)
fn := LegendCustomize(series, LegendOption{ fn := LegendCustomize(series, LegendOption{
TextPosition: LegendTextPositionRight, TextPosition: tt.textPosition,
IconDraw: DefaultLegendIconDraw, IconDraw: DefaultLegendIconDraw,
Align: LegendAlignLeft, Align: LegendAlignLeft,
Padding: chart.Box{ Padding: chart.Box{
@ -58,5 +74,6 @@ func TestLegendCustomize(t *testing.T) {
buf := bytes.Buffer{} buf := bytes.Buffer{}
err = r.Save(&buf) err = r.Save(&buf)
assert.Nil(err) assert.Nil(err)
assert.Equal("<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"800\" height=\"600\">\\n<path d=\"M 100 100\nL 208 100\nL 208 110\nL 100 110\nL 100 100\" style=\"stroke-width:0;stroke:rgba(51,51,51,1.0);fill:none\"/><path d=\"M 100 107\nL 125 107\" style=\"stroke-width:2;stroke:rgba(84,112,198,1.0);fill:none\"/><circle cx=\"112\" cy=\"107\" r=\"5\" style=\"stroke-width:2;stroke:rgba(84,112,198,1.0);fill:rgba(255,255,255,1.0)\"/><path d=\"\" style=\"stroke-width:2;stroke:rgba(84,112,198,1.0);fill:rgba(255,255,255,1.0)\"/><text x=\"130\" y=\"110\" style=\"stroke-width:0;stroke:none;fill:rgba(51,51,51,1.0);font-size:10.2px;font-family:'Roboto Medium',sans-serif\">chrome</text><path d=\"M 185 107\nL 210 107\" style=\"stroke-width:2;stroke:rgba(145,204,117,1.0);fill:rgba(255,255,255,1.0)\"/><circle cx=\"197\" cy=\"107\" r=\"5\" style=\"stroke-width:2;stroke:rgba(145,204,117,1.0);fill:rgba(255,255,255,1.0)\"/><path d=\"\" style=\"stroke-width:2;stroke:rgba(145,204,117,1.0);fill:rgba(255,255,255,1.0)\"/><text x=\"215\" y=\"110\" style=\"stroke-width:0;stroke:none;fill:rgba(51,51,51,1.0);font-size:10.2px;font-family:'Roboto Medium',sans-serif\">edge</text></svg>", buf.String()) assert.Equal(tt.svg, buf.String())
}
} }

View file

@ -30,11 +30,16 @@ type LineSeries struct {
BaseSeries BaseSeries
} }
func (bs LineSeries) Render(r chart.Renderer, canvasBox chart.Box, xrange, yrange chart.Range, defaults chart.Style) { func (ls LineSeries) getXRange(xrange chart.Range) chart.Range {
style := bs.Style.InheritFrom(defaults) if ls.TickPosition != chart.TickPositionBetweenTicks {
return xrange
}
// 如果是居中,画线时重新调整 // 如果是居中,画线时重新调整
if bs.TickPosition == chart.TickPositionBetweenTicks { return wrapRange(xrange, ls.TickPosition)
xrange = wrapRange(xrange, bs.TickPosition)
} }
chart.Draw.LineSeries(r, canvasBox, xrange, yrange, style, bs)
func (ls LineSeries) Render(r chart.Renderer, canvasBox chart.Box, xrange, yrange chart.Range, defaults chart.Style) {
style := ls.Style.InheritFrom(defaults)
xrange = ls.getXRange(xrange)
chart.Draw.LineSeries(r, canvasBox, xrange, yrange, style, ls)
} }

46
line_series_test.go Normal file
View file

@ -0,0 +1,46 @@
// MIT License
// Copyright (c) 2021 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 (
"testing"
"github.com/stretchr/testify/assert"
"github.com/wcharczuk/go-chart/v2"
)
func TestLineSeries(t *testing.T) {
assert := assert.New(t)
ls := LineSeries{}
originalRange := &chart.ContinuousRange{}
xrange := ls.getXRange(originalRange)
assert.Equal(originalRange, xrange)
ls.TickPosition = chart.TickPositionBetweenTicks
xrange = ls.getXRange(originalRange)
value, ok := xrange.(*Range)
assert.True(ok)
assert.Equal(originalRange, &value.ContinuousRange)
}

54
range_test.go Normal file
View file

@ -0,0 +1,54 @@
// MIT License
// Copyright (c) 2021 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 (
"testing"
"github.com/stretchr/testify/assert"
"github.com/wcharczuk/go-chart/v2"
)
func TestRange(t *testing.T) {
assert := assert.New(t)
r := Range{
ContinuousRange: chart.ContinuousRange{
Min: 0,
Max: 5,
Domain: 500,
},
}
assert.Equal(100, r.Translate(1))
r.TickPosition = chart.TickPositionBetweenTicks
assert.Equal(50, r.Translate(1))
}
func TestHiddenRange(t *testing.T) {
assert := assert.New(t)
r := HiddenRange{}
assert.Equal(float64(0), r.GetDelta())
}

View file

@ -108,7 +108,6 @@ func GetSeries(series []Series, tickPosition chart.TickPosition, theme string) [
if item.YAxisIndex != 0 { if item.YAxisIndex != 0 {
baseSeries.YAxis = chart.YAxisPrimary baseSeries.YAxis = chart.YAxisPrimary
} }
// TODO 判断类型
switch item.Type { switch item.Type {
case SeriesBar: case SeriesBar:
arr[index] = BarSeries{ arr[index] = BarSeries{

125
series_test.go Normal file
View file

@ -0,0 +1,125 @@
// MIT License
// Copyright (c) 2021 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 (
"testing"
"github.com/stretchr/testify/assert"
"github.com/wcharczuk/go-chart/v2"
)
func TestNewSeriesDataListFromFloat(t *testing.T) {
assert := assert.New(t)
assert.Equal([]SeriesData{
{
Value: 1,
},
{
Value: 2,
},
}, NewSeriesDataListFromFloat([]float64{
1,
2,
}))
}
func TestGetSeries(t *testing.T) {
assert := assert.New(t)
xValues := []float64{
1,
2,
3,
4,
5,
}
barData := NewSeriesDataListFromFloat([]float64{
10,
20,
30,
40,
50,
})
barData[1].Style = chart.Style{
FillColor: AxisColorDark,
}
seriesList := GetSeries([]Series{
{
Type: SeriesBar,
Data: barData,
XValues: xValues,
YAxisIndex: 1,
},
{
Data: NewSeriesDataListFromFloat([]float64{
11,
21,
31,
41,
51,
}),
XValues: xValues,
},
}, chart.TickPositionBetweenTicks, "")
assert.Equal(seriesList[0].GetYAxis(), chart.YAxisPrimary)
assert.Equal(seriesList[1].GetYAxis(), chart.YAxisSecondary)
barSeries, ok := seriesList[0].(BarSeries)
assert.True(ok)
// 居中前置多插入一个点
assert.Equal([]float64{
0,
10,
20,
30,
40,
50,
}, barSeries.YValues)
assert.Equal(xValues, barSeries.XValues)
assert.Equal(1, barSeries.Count)
assert.Equal(0, barSeries.Index)
assert.Equal([]BarSeriesCustomStyle{
{
PointIndex: 1,
Index: 0,
Style: barData[1].Style,
},
}, barSeries.CustomStyles)
lineSeries, ok := seriesList[1].(LineSeries)
assert.True(ok)
// 居中前置多插入一个点
assert.Equal([]float64{
0,
11,
21,
31,
41,
51,
}, lineSeries.YValues)
assert.Equal(xValues, lineSeries.XValues)
}

View file

@ -23,6 +23,8 @@
package charts package charts
import ( import (
"regexp"
"strconv"
"strings" "strings"
"github.com/wcharczuk/go-chart/v2" "github.com/wcharczuk/go-chart/v2"
@ -44,6 +46,20 @@ var AxisColorDark = drawing.Color{
A: 255, A: 255,
} }
var GridColorDark = drawing.Color{
R: 72,
G: 71,
B: 83,
A: 255,
}
var GridColorLight = drawing.Color{
R: 224,
G: 230,
B: 241,
A: 255,
}
var BackgroundColorDark = drawing.Color{ var BackgroundColorDark = drawing.Color{
R: 16, R: 16,
G: 12, G: 12,
@ -67,19 +83,9 @@ func getAxisColor(theme string) drawing.Color {
func getGridColor(theme string) drawing.Color { func getGridColor(theme string) drawing.Color {
if theme == ThemeDark { if theme == ThemeDark {
return drawing.Color{ return GridColorDark
R: 72,
G: 71,
B: 83,
A: 255,
}
}
return drawing.Color{
R: 224,
G: 230,
B: 241,
A: 255,
} }
return GridColorLight
} }
var SeriesColorsLight = []drawing.Color{ var SeriesColorsLight = []drawing.Color{
@ -180,12 +186,37 @@ func getSeriesColor(theme string, index int) drawing.Color {
} }
func parseColor(color string) drawing.Color { func parseColor(color string) drawing.Color {
c := drawing.Color{}
if color == "" { if color == "" {
return drawing.Color{} return c
} }
if strings.HasPrefix(color, "#") { if strings.HasPrefix(color, "#") {
return drawing.ColorFromHex(color[1:]) return drawing.ColorFromHex(color[1:])
} }
// TODO rgba reg := regexp.MustCompile(`\((\S+)\)`)
return drawing.Color{} result := reg.FindAllStringSubmatch(color, 1)
if len(result) == 0 || len(result[0]) != 2 {
return c
}
arr := strings.Split(result[0][1], ",")
if len(arr) < 3 {
return c
}
// 设置默认为255
c.A = 255
for index, v := range arr {
value, _ := strconv.Atoi(strings.TrimSpace(v))
ui8 := uint8(value)
switch index {
case 0:
c.R = ui8
case 1:
c.G = ui8
case 2:
c.B = ui8
default:
c.A = ui8
}
}
return c
} }

122
theme_test.go Normal file
View file

@ -0,0 +1,122 @@
// MIT License
// Copyright (c) 2021 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 (
"testing"
"github.com/stretchr/testify/assert"
"github.com/wcharczuk/go-chart/v2"
"github.com/wcharczuk/go-chart/v2/drawing"
)
func TestThemeColors(t *testing.T) {
assert := assert.New(t)
assert.Equal(AxisColorDark, getAxisColor(ThemeDark))
assert.Equal(AxisColorLight, getAxisColor(""))
assert.Equal(GridColorDark, getGridColor(ThemeDark))
assert.Equal(GridColorLight, getGridColor(""))
assert.Equal(BackgroundColorDark, getBackgroundColor(ThemeDark))
assert.Equal(chart.DefaultBackgroundColor, getBackgroundColor(""))
assert.Equal(TextColorDark, getTextColor(ThemeDark))
assert.Equal(chart.DefaultTextColor, getTextColor(""))
}
func TestThemeColorPalette(t *testing.T) {
assert := assert.New(t)
dark := ThemeColorPalette{
Theme: ThemeDark,
}
assert.Equal(BackgroundColorDark, dark.BackgroundColor())
assert.Equal(chart.DefaultBackgroundStrokeColor, dark.BackgroundStrokeColor())
assert.Equal(BackgroundColorDark, dark.CanvasColor())
assert.Equal(chart.DefaultCanvasStrokeColor, dark.CanvasStrokeColor())
assert.Equal(BackgroundColorDark, dark.AxisStrokeColor())
assert.Equal(TextColorDark, dark.TextColor())
// series 使用统一的color
assert.Equal(SeriesColorsLight[0], dark.GetSeriesColor(0))
light := ThemeColorPalette{}
assert.Equal(chart.DefaultBackgroundColor, light.BackgroundColor())
assert.Equal(chart.DefaultBackgroundStrokeColor, light.BackgroundStrokeColor())
assert.Equal(chart.DefaultCanvasColor, light.CanvasColor())
assert.Equal(chart.DefaultCanvasStrokeColor, light.CanvasStrokeColor())
assert.Equal(chart.DefaultAxisColor, light.AxisStrokeColor())
assert.Equal(chart.DefaultTextColor, light.TextColor())
// series 使用统一的color
assert.Equal(SeriesColorsLight[0], light.GetSeriesColor(0))
}
func TestPieThemeColorPalette(t *testing.T) {
assert := assert.New(t)
p := PieThemeColorPalette{}
// pie无认哪种theme文本的颜色都一样
assert.Equal(chart.DefaultTextColor, p.TextColor())
p.Theme = ThemeDark
assert.Equal(chart.DefaultTextColor, p.TextColor())
}
func TestParseColor(t *testing.T) {
assert := assert.New(t)
c := parseColor("")
assert.True(c.IsZero())
c = parseColor("#333")
assert.Equal(drawing.Color{
R: 51,
G: 51,
B: 51,
A: 255,
}, c)
c = parseColor("#313233")
assert.Equal(drawing.Color{
R: 49,
G: 50,
B: 51,
A: 255,
}, c)
c = parseColor("rgb(31,32,33)")
assert.Equal(drawing.Color{
R: 31,
G: 32,
B: 33,
A: 255,
}, c)
c = parseColor("rgba(50,51,52,250)")
assert.Equal(drawing.Color{
R: 50,
G: 51,
B: 52,
A: 250,
}, c)
}