diff --git a/echarts.go b/echarts.go
index b0cbe8a..02cede2 100644
--- a/echarts.go
+++ b/echarts.go
@@ -112,12 +112,15 @@ func (ep *EChartsPadding) UnmarshalJSON(data []byte) error {
default:
result := make([]int, 4)
copy(result, arr)
+ if len(arr) == 3 {
+ result[3] = result[1]
+ }
// 上右下左
ep.box = chart.Box{
- Top: arr[0],
- Right: arr[1],
- Bottom: arr[2],
- Left: arr[3],
+ Top: result[0],
+ Right: result[1],
+ Bottom: result[2],
+ Left: result[3],
}
}
return nil
diff --git a/echarts_test.go b/echarts_test.go
new file mode 100644
index 0000000..99bf414
--- /dev/null
+++ b/echarts_test.go
@@ -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)
+}
diff --git a/legend.go b/legend.go
index b519e3e..b019868 100644
--- a/legend.go
+++ b/legend.go
@@ -87,6 +87,7 @@ func LegendCustomize(series []chart.Series, opt LegendOption) chart.Renderable {
var labels []string
var lines []chart.Style
+ // 计算label和lines
for _, s := range series {
if !s.GetStyle().Hidden {
if _, isAnnotationSeries := s.(chart.AnnotationSeries); !isAnnotationSeries {
@@ -100,6 +101,7 @@ func LegendCustomize(series []chart.Series, opt LegendOption) chart.Renderable {
var textWidth int
var textBox chart.Box
labelWidth := 0
+ // 计算文本宽度与高度(取最大值)
for x := 0; x < len(labels); x++ {
if len(labels[x]) > 0 {
textBox = r.MeasureText(labels[x])
diff --git a/legend_test.go b/legend_test.go
index 6685243..d2af129 100644
--- a/legend_test.go
+++ b/legend_test.go
@@ -41,22 +41,39 @@ func TestLegendCustomize(t *testing.T) {
Name: "edge",
},
}, chart.TickPositionBetweenTicks, "")
- r, err := chart.SVG(800, 600)
- assert.Nil(err)
- fn := LegendCustomize(series, LegendOption{
- TextPosition: LegendTextPositionRight,
- IconDraw: DefaultLegendIconDraw,
- Align: LegendAlignLeft,
- Padding: chart.Box{
- Left: 100,
- Top: 100,
+
+ tests := []struct {
+ textPosition string
+ svg string
+ }{
+ {
+ textPosition: LegendTextPositionRight,
+ svg: "",
},
- })
- fn(r, chart.NewBox(11, 47, 784, 373), chart.Style{
- Font: chart.StyleTextDefaults().Font,
- })
- buf := bytes.Buffer{}
- err = r.Save(&buf)
- assert.Nil(err)
- assert.Equal("", buf.String())
+ {
+ textPosition: LegendAlignLeft,
+ svg: "",
+ },
+ }
+
+ for _, tt := range tests {
+ r, err := chart.SVG(800, 600)
+ assert.Nil(err)
+ fn := LegendCustomize(series, LegendOption{
+ TextPosition: tt.textPosition,
+ IconDraw: DefaultLegendIconDraw,
+ Align: LegendAlignLeft,
+ Padding: chart.Box{
+ Left: 100,
+ Top: 100,
+ },
+ })
+ fn(r, chart.NewBox(11, 47, 784, 373), chart.Style{
+ Font: chart.StyleTextDefaults().Font,
+ })
+ buf := bytes.Buffer{}
+ err = r.Save(&buf)
+ assert.Nil(err)
+ assert.Equal(tt.svg, buf.String())
+ }
}
diff --git a/line_series.go b/line_series.go
index 5b7c9fd..f3686ad 100644
--- a/line_series.go
+++ b/line_series.go
@@ -30,11 +30,16 @@ type LineSeries struct {
BaseSeries
}
-func (bs LineSeries) Render(r chart.Renderer, canvasBox chart.Box, xrange, yrange chart.Range, defaults chart.Style) {
- style := bs.Style.InheritFrom(defaults)
- // 如果是居中,画线时重新调整
- if bs.TickPosition == chart.TickPositionBetweenTicks {
- xrange = wrapRange(xrange, bs.TickPosition)
+func (ls LineSeries) getXRange(xrange chart.Range) chart.Range {
+ if ls.TickPosition != chart.TickPositionBetweenTicks {
+ return xrange
}
- chart.Draw.LineSeries(r, canvasBox, xrange, yrange, style, bs)
+ // 如果是居中,画线时重新调整
+ return wrapRange(xrange, ls.TickPosition)
+}
+
+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)
}
diff --git a/line_series_test.go b/line_series_test.go
new file mode 100644
index 0000000..27c9371
--- /dev/null
+++ b/line_series_test.go
@@ -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)
+}
diff --git a/range_test.go b/range_test.go
new file mode 100644
index 0000000..3e80568
--- /dev/null
+++ b/range_test.go
@@ -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())
+}
diff --git a/series.go b/series.go
index 67d8c4d..37e6c71 100644
--- a/series.go
+++ b/series.go
@@ -108,7 +108,6 @@ func GetSeries(series []Series, tickPosition chart.TickPosition, theme string) [
if item.YAxisIndex != 0 {
baseSeries.YAxis = chart.YAxisPrimary
}
- // TODO 判断类型
switch item.Type {
case SeriesBar:
arr[index] = BarSeries{
diff --git a/series_test.go b/series_test.go
new file mode 100644
index 0000000..5016aab
--- /dev/null
+++ b/series_test.go
@@ -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)
+}
diff --git a/theme.go b/theme.go
index a86b282..051e099 100644
--- a/theme.go
+++ b/theme.go
@@ -23,6 +23,8 @@
package charts
import (
+ "regexp"
+ "strconv"
"strings"
"github.com/wcharczuk/go-chart/v2"
@@ -44,6 +46,20 @@ var AxisColorDark = drawing.Color{
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{
R: 16,
G: 12,
@@ -67,19 +83,9 @@ func getAxisColor(theme string) drawing.Color {
func getGridColor(theme string) drawing.Color {
if theme == ThemeDark {
- return drawing.Color{
- R: 72,
- G: 71,
- B: 83,
- A: 255,
- }
- }
- return drawing.Color{
- R: 224,
- G: 230,
- B: 241,
- A: 255,
+ return GridColorDark
}
+ return GridColorLight
}
var SeriesColorsLight = []drawing.Color{
@@ -180,12 +186,37 @@ func getSeriesColor(theme string, index int) drawing.Color {
}
func parseColor(color string) drawing.Color {
+ c := drawing.Color{}
if color == "" {
- return drawing.Color{}
+ return c
}
if strings.HasPrefix(color, "#") {
return drawing.ColorFromHex(color[1:])
}
- // TODO rgba
- return drawing.Color{}
+ reg := regexp.MustCompile(`\((\S+)\)`)
+ 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
}
diff --git a/theme_test.go b/theme_test.go
new file mode 100644
index 0000000..a25a2db
--- /dev/null
+++ b/theme_test.go
@@ -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)
+}