From c15fec21ad3b2c5a05c30b75b410cfeb38708aae Mon Sep 17 00:00:00 2001 From: vicanso Date: Thu, 17 Feb 2022 22:53:12 +0800 Subject: [PATCH] test: add test for echart --- bar_chart.go | 8 +- bar_chart_test.go | 2 - chart.go | 5 + chart_test.go | 226 ++++++++++ draw.go | 2 +- echarts.go | 60 ++- echarts_test.go | 258 +++++++++++ examples/demo/main.go | 998 ++++++++++++++++++++++++++++++++++++++++-- legend_test.go | 2 - mark_point_test.go | 2 - 10 files changed, 1516 insertions(+), 47 deletions(-) diff --git a/bar_chart.go b/bar_chart.go index f291d78..e008baf 100644 --- a/bar_chart.go +++ b/bar_chart.go @@ -54,7 +54,10 @@ func barChartRender(opt barChartOption, result *basicRenderResult) ([]markPointR margin := 10 // 每一个bar之间的margin barMargin := 5 - if width < 50 { + if width < 20 { + margin = 2 + barMargin = 2 + } else if width < 50 { margin = 5 barMargin = 3 } @@ -95,6 +98,9 @@ func barChartRender(opt barChartOption, result *basicRenderResult) ([]markPointR }) divideValues := xRange.AutoDivide() for j, item := range series.Data { + if j >= len(divideValues) { + continue + } x := divideValues[j] x += margin if i != 0 { diff --git a/bar_chart_test.go b/bar_chart_test.go index 2351e1a..f10a1bc 100644 --- a/bar_chart_test.go +++ b/bar_chart_test.go @@ -23,7 +23,6 @@ package charts import ( - "fmt" "testing" "github.com/stretchr/testify/assert" @@ -128,6 +127,5 @@ func TestBarChartRender(t *testing.T) { data, err := d.Bytes() assert.Nil(err) - fmt.Println(string(data)) assert.Equal("\\n20206090", string(data)) } diff --git a/chart.go b/chart.go index c211a6d..5178b04 100644 --- a/chart.go +++ b/chart.go @@ -38,6 +38,11 @@ const ( ChartTypePie = "pie" ) +const ( + ChartOutputSVG = "svg" + ChartOutputPNG = "png" +) + type Point struct { X int Y int diff --git a/chart_test.go b/chart_test.go index ee768ec..4fc3d20 100644 --- a/chart_test.go +++ b/chart_test.go @@ -23,6 +23,7 @@ package charts import ( + "errors" "testing" "github.com/stretchr/testify/assert" @@ -276,3 +277,228 @@ func TestChartRender(t *testing.T) { assert.Nil(err) assert.Equal("\\n2012201320142015201620170153045607590Milk TeaMatcha LatteCheese CocoaWalnut BrownieMilk Tea: 34.03%Matcha Latte: 27.66%Cheese Cocoa: 22.32%Walnut Brownie: 15.96%", string(data)) } + +func BenchmarkMultiChartPNGRender(b *testing.B) { + for i := 0; i < b.N; i++ { + opt := ChartOption{ + Type: ChartOutputPNG, + Legend: LegendOption{ + Top: "-90", + Data: []string{ + "Milk Tea", + "Matcha Latte", + "Cheese Cocoa", + "Walnut Brownie", + }, + }, + Padding: chart.Box{ + Top: 100, + Right: 10, + Bottom: 10, + Left: 10, + }, + XAxis: NewXAxisOption([]string{ + "2012", + "2013", + "2014", + "2015", + "2016", + "2017", + }), + YAxisList: []YAxisOption{ + { + + Min: NewFloatPoint(0), + Max: NewFloatPoint(90), + }, + }, + SeriesList: []Series{ + NewSeriesFromValues([]float64{ + 56.5, + 82.1, + 88.7, + 70.1, + 53.4, + 85.1, + }), + NewSeriesFromValues([]float64{ + 51.1, + 51.4, + 55.1, + 53.3, + 73.8, + 68.7, + }), + NewSeriesFromValues([]float64{ + 40.1, + 62.2, + 69.5, + 36.4, + 45.2, + 32.5, + }, ChartTypeBar), + NewSeriesFromValues([]float64{ + 25.2, + 37.1, + 41.2, + 18, + 33.9, + 49.1, + }, ChartTypeBar), + }, + Children: []ChartOption{ + { + Legend: LegendOption{ + Show: FalseFlag(), + Data: []string{ + "Milk Tea", + "Matcha Latte", + "Cheese Cocoa", + "Walnut Brownie", + }, + }, + Box: chart.Box{ + Top: 20, + Left: 400, + Right: 500, + Bottom: 120, + }, + SeriesList: NewPieSeriesList([]float64{ + 435.9, + 354.3, + 285.9, + 204.5, + }, PieSeriesOption{ + Label: SeriesLabel{ + Show: true, + }, + Radius: "35%", + }), + }, + }, + } + d, err := Render(opt) + if err != nil { + panic(err) + } + buf, err := d.Bytes() + if err != nil { + panic(err) + } + if len(buf) == 0 { + panic(errors.New("data is nil")) + } + } +} + +func BenchmarkMultiChartSVGRender(b *testing.B) { + for i := 0; i < b.N; i++ { + opt := ChartOption{ + Legend: LegendOption{ + Top: "-90", + Data: []string{ + "Milk Tea", + "Matcha Latte", + "Cheese Cocoa", + "Walnut Brownie", + }, + }, + Padding: chart.Box{ + Top: 100, + Right: 10, + Bottom: 10, + Left: 10, + }, + XAxis: NewXAxisOption([]string{ + "2012", + "2013", + "2014", + "2015", + "2016", + "2017", + }), + YAxisList: []YAxisOption{ + { + + Min: NewFloatPoint(0), + Max: NewFloatPoint(90), + }, + }, + SeriesList: []Series{ + NewSeriesFromValues([]float64{ + 56.5, + 82.1, + 88.7, + 70.1, + 53.4, + 85.1, + }), + NewSeriesFromValues([]float64{ + 51.1, + 51.4, + 55.1, + 53.3, + 73.8, + 68.7, + }), + NewSeriesFromValues([]float64{ + 40.1, + 62.2, + 69.5, + 36.4, + 45.2, + 32.5, + }, ChartTypeBar), + NewSeriesFromValues([]float64{ + 25.2, + 37.1, + 41.2, + 18, + 33.9, + 49.1, + }, ChartTypeBar), + }, + Children: []ChartOption{ + { + Legend: LegendOption{ + Show: FalseFlag(), + Data: []string{ + "Milk Tea", + "Matcha Latte", + "Cheese Cocoa", + "Walnut Brownie", + }, + }, + Box: chart.Box{ + Top: 20, + Left: 400, + Right: 500, + Bottom: 120, + }, + SeriesList: NewPieSeriesList([]float64{ + 435.9, + 354.3, + 285.9, + 204.5, + }, PieSeriesOption{ + Label: SeriesLabel{ + Show: true, + }, + Radius: "35%", + }), + }, + }, + } + d, err := Render(opt) + if err != nil { + panic(err) + } + buf, err := d.Bytes() + if err != nil { + panic(err) + } + if len(buf) == 0 { + panic(errors.New("data is nil")) + } + } +} diff --git a/draw.go b/draw.go index 228f622..bc3d9e8 100644 --- a/draw.go +++ b/draw.go @@ -114,7 +114,7 @@ func NewDraw(opt DrawOption, opts ...Option) (*Draw, error) { // 创建render if d.parent == nil { fn := chart.SVG - if opt.Type == "png" { + if opt.Type == ChartOutputPNG { fn = chart.PNG } r, err := fn(d.Box.Right, d.Box.Bottom) diff --git a/echarts.go b/echarts.go index 9232ed7..dc2e761 100644 --- a/echarts.go +++ b/echarts.go @@ -76,12 +76,14 @@ type EChartsSeriesData struct { } type _EChartsSeriesData EChartsSeriesData +var numericRep = regexp.MustCompile("^[-+]?[0-9]+(?:\\.[0-9]+)?$") + func (es *EChartsSeriesData) UnmarshalJSON(data []byte) error { data = bytes.TrimSpace(data) if len(data) == 0 { return nil } - if regexp.MustCompile(`^\d+`).Match(data) { + if numericRep.Match(data) { v, err := strconv.ParseFloat(string(data), 64) if err != nil { return err @@ -215,16 +217,20 @@ type EChartsMarkPoint struct { } func (emp *EChartsMarkPoint) ToSeriesMarkPoint() SeriesMarkPoint { + sp := SeriesMarkPoint{ + SymbolSize: emp.SymbolSize, + } + if len(emp.Data) == 0 { + return sp + } data := make([]SeriesMarkData, len(emp.Data)) for index, item := range emp.Data { data[index] = SeriesMarkData{ Type: item.Type, } } - return SeriesMarkPoint{ - Data: data, - SymbolSize: emp.SymbolSize, - } + sp.Data = data + return sp } type EChartsMarkLine struct { @@ -234,15 +240,18 @@ type EChartsMarkLine struct { } func (eml *EChartsMarkLine) ToSeriesMarkLine() SeriesMarkLine { + sl := SeriesMarkLine{} + if len(eml.Data) == 0 { + return sl + } data := make([]SeriesMarkData, len(eml.Data)) for index, item := range eml.Data { data[index] = SeriesMarkData{ Type: item.Type, } } - return SeriesMarkLine{ - Data: data, - } + sl.Data = data + return sl } type EChartsSeries struct { @@ -260,8 +269,27 @@ type EChartsSeries struct { type EChartsSeriesList []EChartsSeries func (esList EChartsSeriesList) ToSeriesList() SeriesList { - seriesList := make(SeriesList, len(esList)) - for index, item := range esList { + seriesList := make(SeriesList, 0, len(esList)) + for _, item := range esList { + // 如果是pie,则每个子荐生成一个series + if item.Type == ChartTypePie { + for _, dataItem := range item.Data { + seriesList = append(seriesList, Series{ + Type: ChartTypePie, + Name: dataItem.Name, + Label: SeriesLabel{ + Show: true, + }, + Radius: item.Radius, + Data: []SeriesData{ + { + Value: dataItem.Value, + }, + }, + }) + } + continue + } data := make([]SeriesData, len(item.Data)) for j, dataItem := range item.Data { data[j] = SeriesData{ @@ -269,7 +297,7 @@ func (esList EChartsSeriesList) ToSeriesList() SeriesList { Style: dataItem.ItemStyle.ToStyle(), } } - seriesList[index] = Series{ + seriesList = append(seriesList, Series{ Type: item.Type, Data: data, YAxisIndex: item.YAxisIndex, @@ -280,10 +308,9 @@ func (esList EChartsSeriesList) ToSeriesList() SeriesList { Distance: item.Label.Distance, }, Name: item.Name, - Radius: item.Radius, MarkPoint: item.MarkPoint.ToSeriesMarkPoint(), MarkLine: item.MarkLine.ToSeriesMarkLine(), - } + }) } return seriesList } @@ -295,10 +322,14 @@ type EChartsTextStyle struct { } func (et *EChartsTextStyle) ToStyle() chart.Style { - return chart.Style{ + s := chart.Style{ FontSize: et.FontSize, FontColor: parseColor(et.Color), } + if et.FontFamily != "" { + s.Font, _ = GetFont(et.FontFamily) + } + return s } type EChartsOption struct { @@ -373,6 +404,7 @@ func (eo *EChartsOption) ToOption() ChartOption { Color: parseColor(item.AxisLine.LineStyle.Color), } } + o.YAxisList = yAxisOptions if len(eo.Children) != 0 { o.Children = make([]ChartOption, len(eo.Children)) diff --git a/echarts_test.go b/echarts_test.go index 3cefb5a..d80ecbb 100644 --- a/echarts_test.go +++ b/echarts_test.go @@ -28,6 +28,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/wcharczuk/go-chart/v2" + "github.com/wcharczuk/go-chart/v2/drawing" ) func TestEChartsPosition(t *testing.T) { @@ -42,6 +43,24 @@ func TestEChartsPosition(t *testing.T) { assert.Nil(err) assert.Equal("12%", string(p)) } +func TestEChartStyle(t *testing.T) { + assert := assert.New(t) + + s := EChartStyle{ + Color: "#aaa", + } + r := drawing.Color{ + R: 170, + G: 170, + B: 170, + A: 255, + } + assert.Equal(chart.Style{ + FillColor: r, + FontColor: r, + StrokeColor: r, + }, s.ToStyle()) +} func TestEChartsXAxis(t *testing.T) { assert := assert.New(t) @@ -299,3 +318,242 @@ func TestEChartsSeries(t *testing.T) { }, }, esList) } + +func TestEChartsMarkPoint(t *testing.T) { + assert := assert.New(t) + + p := EChartsMarkPoint{} + + err := json.Unmarshal([]byte(`{ + "symbolSize": 30, + "data": [ + { + "type": "max" + }, + { + "type": "min" + } + ] + }`), &p) + assert.Nil(err) + assert.Equal(SeriesMarkPoint{ + SymbolSize: 30, + Data: []SeriesMarkData{ + { + Type: "max", + }, + { + Type: "min", + }, + }, + }, p.ToSeriesMarkPoint()) +} + +func TestEChartsMarkLine(t *testing.T) { + assert := assert.New(t) + l := EChartsMarkLine{} + + err := json.Unmarshal([]byte(`{ + "data": [ + { + "type": "max" + }, + { + "type": "min" + } + ] + }`), &l) + assert.Nil(err) + assert.Equal(SeriesMarkLine{ + Data: []SeriesMarkData{ + { + Type: "max", + }, + { + Type: "min", + }, + }, + }, l.ToSeriesMarkLine()) +} + +func TestEChartsTextStyle(t *testing.T) { + assert := assert.New(t) + + s := EChartsTextStyle{ + Color: "#aaa", + FontFamily: "test", + FontSize: 14, + } + assert.Equal(chart.Style{ + FontColor: drawing.Color{ + R: 170, + G: 170, + B: 170, + A: 255, + }, + FontSize: 14, + }, s.ToStyle()) +} + +func TestEChartsSeriesList(t *testing.T) { + assert := assert.New(t) + + // pie + es := EChartsSeriesList{ + { + Type: ChartTypePie, + Radius: "30%", + Data: []EChartsSeriesData{ + { + Name: "1", + Value: 1, + }, + { + Name: "2", + Value: 2, + }, + }, + }, + } + assert.Equal(SeriesList{ + { + Type: ChartTypePie, + Name: "1", + Label: SeriesLabel{ + Show: true, + }, + Radius: "30%", + Data: []SeriesData{ + { + Value: 1, + }, + }, + }, + { + Type: ChartTypePie, + Name: "2", + Label: SeriesLabel{ + Show: true, + }, + Radius: "30%", + Data: []SeriesData{ + { + Value: 2, + }, + }, + }, + }, es.ToSeriesList()) + + es = EChartsSeriesList{ + { + Type: ChartTypeBar, + Data: []EChartsSeriesData{ + { + Value: 1, + ItemStyle: EChartStyle{ + Color: "#aaa", + }, + }, + { + Value: 2, + }, + }, + YAxisIndex: 1, + }, + { + Data: []EChartsSeriesData{ + { + Value: 3, + }, + { + Value: 4, + }, + }, + ItemStyle: EChartStyle{ + Color: "#ccc", + }, + Label: EChartsLabelOption{ + Color: "#ddd", + Show: true, + Distance: 5, + }, + }, + } + assert.Equal(SeriesList{ + { + Type: ChartTypeBar, + Data: []SeriesData{ + { + Value: 1, + Style: chart.Style{ + FontColor: drawing.Color{ + R: 170, + G: 170, + B: 170, + A: 255, + }, + StrokeColor: drawing.Color{ + R: 170, + G: 170, + B: 170, + A: 255, + }, + FillColor: drawing.Color{ + R: 170, + G: 170, + B: 170, + A: 255, + }, + }, + }, + { + Value: 2, + }, + }, + YAxisIndex: 1, + }, + { + Data: []SeriesData{ + { + Value: 3, + }, + { + Value: 4, + }, + }, + Style: chart.Style{ + FontColor: drawing.Color{ + R: 204, + G: 204, + B: 204, + A: 255, + }, + StrokeColor: drawing.Color{ + R: 204, + G: 204, + B: 204, + A: 255, + }, + FillColor: drawing.Color{ + R: 204, + G: 204, + B: 204, + A: 255, + }, + }, + Label: SeriesLabel{ + Color: drawing.Color{ + R: 221, + G: 221, + B: 221, + A: 255, + }, + Show: true, + Distance: 5, + }, + MarkPoint: SeriesMarkPoint{}, + MarkLine: SeriesMarkLine{}, + }, + }, es.ToSeriesList()) + +} diff --git a/examples/demo/main.go b/examples/demo/main.go index 7916b4d..4ab6b04 100644 --- a/examples/demo/main.go +++ b/examples/demo/main.go @@ -62,8 +62,9 @@ var html = ` ` -func indexHandler(w http.ResponseWriter, req *http.Request) { - if req.URL.Path != "/" { +func handler(w http.ResponseWriter, req *http.Request, chartOptions []charts.ChartOption, echartsOptions []string) { + if req.URL.Path != "/" && + req.URL.Path != "/echarts" { return } query := req.URL.Query() @@ -72,10 +73,36 @@ func indexHandler(w http.ResponseWriter, req *http.Request) { height, _ := strconv.Atoi(query.Get("height")) charts.SetDefaultWidth(width) charts.SetDefaultWidth(height) + bytesList := make([][]byte, 0) + for _, opt := range chartOptions { + opt.Theme = theme + d, err := charts.Render(opt) + if err != nil { + panic(err) + } + buf, err := d.Bytes() + if err != nil { + panic(err) + } + bytesList = append(bytesList, buf) + } + for _, opt := range echartsOptions { + buf, err := charts.RenderEChartsToSVG(opt) + 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 indexHandler(w http.ResponseWriter, req *http.Request) { chartOptions := []charts.ChartOption{ // 普通折线图 { - Theme: theme, Title: charts.TitleOption{ Text: "Line", }, @@ -145,7 +172,6 @@ func indexHandler(w http.ResponseWriter, req *http.Request) { }, // 温度折线图 { - Theme: theme, Title: charts.TitleOption{ Text: "Temperature Change in the Coming Week", }, @@ -198,7 +224,6 @@ func indexHandler(w http.ResponseWriter, req *http.Request) { }, // 柱状图 { - Theme: theme, Title: charts.TitleOption{ Text: "Bar", }, @@ -263,7 +288,6 @@ func indexHandler(w http.ResponseWriter, req *http.Request) { }, // 柱状图+mark { - Theme: theme, Title: charts.TitleOption{ Text: "Rainfall vs Evaporation", Subtext: "Fake Data", @@ -345,7 +369,6 @@ func indexHandler(w http.ResponseWriter, req *http.Request) { }, // 双Y轴示例 { - Theme: theme, XAxis: charts.NewXAxisOption([]string{ "Jan", "Feb", @@ -442,7 +465,6 @@ func indexHandler(w http.ResponseWriter, req *http.Request) { }, // 饼图 { - Theme: theme, Title: charts.TitleOption{ Text: "Referer of a Website", Subtext: "Fake Data", @@ -474,7 +496,6 @@ func indexHandler(w http.ResponseWriter, req *http.Request) { }, // 多图展示 { - Theme: theme, Legend: charts.LegendOption{ Top: "-90", Data: []string{ @@ -485,7 +506,10 @@ func indexHandler(w http.ResponseWriter, req *http.Request) { }, }, Padding: chart.Box{ - Top: 100, + Top: 100, + Right: 10, + Bottom: 10, + Left: 10, }, XAxis: charts.NewXAxisOption([]string{ "2012", @@ -568,25 +592,949 @@ func indexHandler(w http.ResponseWriter, req *http.Request) { }, }, } - 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) + handler(w, req, chartOptions, nil) +} +func echartsHandler(w http.ResponseWriter, req *http.Request) { + echartsOptions := []string{ + `{ + "xAxis": { + "type": "category", + "data": [ + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat", + "Sun" + ] + }, + "yAxis": { + "type": "value" + }, + "series": [ + { + "data": [ + 150, + 230, + 224, + 218, + 135, + 147, + 260 + ], + "type": "line" + } + ] + }`, + `{ + "title": { + "text": "Multiple Line" + }, + "tooltip": { + "trigger": "axis" + }, + "legend": { + "left": "right", + "data": [ + "Email", + "Union Ads", + "Video Ads", + "Direct", + "Search Engine" + ] + }, + "grid": { + "left": "3%", + "right": "4%", + "bottom": "3%", + "containLabel": true + }, + "toolbox": { + "feature": { + "saveAsImage": {} + } + }, + "xAxis": { + "type": "category", + "boundaryGap": false, + "data": [ + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat", + "Sun" + ] + }, + "yAxis": { + "type": "value" + }, + "series": [ + { + "name": "Email", + "type": "line", + "data": [ + 120, + 132, + 101, + 134, + 90, + 230, + 210 + ] + }, + { + "name": "Union Ads", + "type": "line", + "data": [ + 220, + 182, + 191, + 234, + 290, + 330, + 310 + ] + }, + { + "name": "Video Ads", + "type": "line", + "data": [ + 150, + 232, + 201, + 154, + 190, + 330, + 410 + ] + }, + { + "name": "Direct", + "type": "line", + "data": [ + 320, + 332, + 301, + 334, + 390, + 330, + 320 + ] + }, + { + "name": "Search Engine", + "type": "line", + "data": [ + 820, + 932, + 901, + 934, + 1290, + 1330, + 1320 + ] + } + ] + }`, + `{ + "title": { + "text": "Temperature Change in the Coming Week" + }, + "legend": { + "left": "right" + }, + "padding": [10, 30, 10, 10], + "xAxis": { + "type": "category", + "boundaryGap": false, + "data": [ + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat", + "Sun" + ] + }, + "yAxis": { + "axisLabel": { + "formatter": "{value} °C" + } + }, + "series": [ + { + "name": "Highest", + "type": "line", + "data": [ + 10, + 11, + 13, + 11, + 12, + 12, + 9 + ], + "markPoint": { + "data": [ + { + "type": "max" + }, + { + "type": "min" + } + ] + }, + "markLine": { + "data": [ + { + "type": "average" + } + ] + } + }, + { + "name": "Lowest", + "type": "line", + "data": [ + 1, + -2, + 2, + 5, + 3, + 2, + 0 + ], + "markPoint": { + "data": [ + { + "type": "min" + } + ] + }, + "markLine": { + "data": [ + { + "type": "average" + }, + { + "type": "max" + } + ] + } + } + ] + }`, + `{ + "xAxis": { + "type": "category", + "data": [ + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat", + "Sun" + ] + }, + "yAxis": { + "type": "value" + }, + "series": [ + { + "data": [ + 120, + 200, + 150, + 80, + 70, + 110, + 130 + ], + "type": "bar" + } + ] + }`, + `{ + "xAxis": { + "type": "category", + "data": [ + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat", + "Sun" + ] + }, + "yAxis": { + "type": "value" + }, + "series": [ + { + "data": [ + 120, + { + "value": 200, + "itemStyle": { + "color": "#a90000" + } + }, + 150, + 80, + 70, + 110, + 130 + ], + "type": "bar" + } + ] + }`, + `{ + "title": { + "text": "Rainfall vs Evaporation", + "subtext": "Fake Data" + }, + "legend": { + "data": [ + "Rainfall", + "Evaporation" + ] + }, + "padding": [10, 30, 10, 10], + "xAxis": [ + { + "type": "category", + "data": [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" + ] + } + ], + "series": [ + { + "name": "Rainfall", + "type": "bar", + "data": [ + 2, + 4.9, + 7, + 23.2, + 25.6, + 76.7, + 135.6, + 162.2, + 32.6, + 20, + 6.4, + 3.3 + ], + "markPoint": { + "data": [ + { + "type": "max" + }, + { + "type": "min" + } + ] + }, + "markLine": { + "data": [ + { + "type": "average" + } + ] + } + }, + { + "name": "Evaporation", + "type": "bar", + "data": [ + 2.6, + 5.9, + 9, + 26.4, + 28.7, + 70.7, + 175.6, + 182.2, + 48.7, + 18.8, + 6, + 2.3 + ], + "markPoint": { + "data": [ + { + "type": "max" + }, + { + "type": "min" + } + ] + }, + "markLine": { + "data": [ + { + "type": "average" + } + ] + } + } + ] + }`, + `{ + "legend": { + "data": [ + "Evaporation", + "Precipitation", + "Temperature" + ] + }, + "xAxis": [ + { + "type": "category", + "data": [ + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat", + "Sun" + ], + "axisPointer": { + "type": "shadow" + } + } + ], + "yAxis": [ + { + "type": "value", + "name": "Precipitation", + "min": 0, + "max": 240, + "axisLabel": { + "formatter": "{value} ml" + } + }, + { + "type": "value", + "name": "Temperature", + "min": 0, + "max": 24, + "axisLabel": { + "formatter": "{value} °C" + } + } + ], + "series": [ + { + "name": "Evaporation", + "type": "bar", + "tooltip": {}, + "data": [ + 2, + 4.9, + 7, + 23.2, + 25.6, + 76.7, + 135.6, + 162.2, + 32.6, + 20, + 6.4, + 3.3 + ] + }, + { + "name": "Precipitation", + "type": "bar", + "tooltip": {}, + "data": [ + 2.6, + 5.9, + 9, + 26.4, + 28.7, + 70.7, + 175.6, + 182.2, + 48.7, + 18.8, + 6, + 2.3 + ] + }, + { + "name": "Temperature", + "type": "line", + "yAxisIndex": 1, + "tooltip": {}, + "data": [ + 2, + 2.2, + 3.3, + 4.5, + 6.3, + 10.2, + 20.3, + 23.4, + 23, + 16.5, + 12, + 6.2 + ] + } + ] + }`, + `{ + "tooltip": { + "trigger": "axis", + "axisPointer": { + "type": "cross" + } + }, + "grid": { + "right": "20%" + }, + "toolbox": { + "feature": { + "dataView": { + "show": true, + "readOnly": false + }, + "restore": { + "show": true + }, + "saveAsImage": { + "show": true + } + } + }, + "legend": { + "data": [ + "Evaporation", + "Precipitation", + "Temperature" + ] + }, + "xAxis": [ + { + "type": "category", + "axisTick": { + "alignWithLabel": true + }, + "data": [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" + ] + } + ], + "yAxis": [ + { + "type": "value", + "name": "温度", + "position": "left", + "alignTicks": true, + "axisLine": { + "show": true, + "lineStyle": { + "color": "#EE6666" + } + }, + "axisLabel": { + "formatter": "{value} °C" + } + }, + { + "type": "value", + "name": "Evaporation", + "position": "right", + "alignTicks": true, + "axisLine": { + "show": true, + "lineStyle": { + "color": "#5470C6" + } + }, + "axisLabel": { + "formatter": "{value} ml" + } + } + ], + "series": [ + { + "name": "Evaporation", + "type": "bar", + "yAxisIndex": 1, + "data": [ + 2, + 4.9, + 7, + 23.2, + 25.6, + 76.7, + 135.6, + 162.2, + 32.6, + 20, + 6.4, + 3.3 + ] + }, + { + "name": "Precipitation", + "type": "bar", + "yAxisIndex": 1, + "data": [ + 2.6, + 5.9, + 9, + 26.4, + 28.7, + 70.7, + 175.6, + 182.2, + 48.7, + 18.8, + 6, + 2.3 + ] + }, + { + "name": "Temperature", + "type": "line", + "data": [ + 2, + 2.2, + 3.3, + 4.5, + 6.3, + 10.2, + 20.3, + 23.4, + 23, + 16.5, + 12, + 6.2 + ] + } + ] + }`, + `{ + "title": { + "text": "Referer of a Website", + "subtext": "Fake Data", + "left": "center" + }, + "tooltip": { + "trigger": "item" + }, + "legend": { + "orient": "vertical", + "left": "left" + }, + "series": [ + { + "name": "Access From", + "type": "pie", + "radius": "50%", + "data": [ + { + "value": 1048, + "name": "Search Engine" + }, + { + "value": 735, + "name": "Direct" + }, + { + "value": 580, + "name": "Email" + }, + { + "value": 484, + "name": "Union Ads" + }, + { + "value": 300, + "name": "Video Ads" + } + ] + } + ] + }`, + `{ + "title": { + "text": "Rainfall" + }, + "padding": [10, 10, 10, 30], + "legend": { + "data": [ + "GZ", + "SH" + ] + }, + "xAxis": { + "type": "category", + "splitNumber": 6, + "data": [ + "01-01", + "01-02", + "01-03", + "01-04", + "01-05", + "01-06", + "01-07", + "01-08", + "01-09", + "01-10", + "01-11", + "01-12", + "01-13", + "01-14", + "01-15", + "01-16", + "01-17", + "01-18", + "01-19", + "01-20", + "01-21", + "01-22", + "01-23", + "01-24", + "01-25", + "01-26", + "01-27", + "01-28", + "01-29", + "01-30", + "01-31" + ] + }, + "yAxis": { + "axisLabel": { + "formatter": "{value} mm" + } + }, + "series": [ + { + "type": "bar", + "data": [ + 928, + 821, + 889, + 600, + 547, + 783, + 197, + 853, + 430, + 346, + 63, + 465, + 309, + 334, + 141, + 538, + 792, + 58, + 922, + 807, + 298, + 243, + 744, + 885, + 812, + 231, + 330, + 220, + 984, + 221, + 429 + ] + }, + { + "type": "bar", + "data": [ + 749, + 201, + 296, + 579, + 255, + 159, + 902, + 246, + 149, + 158, + 507, + 776, + 186, + 79, + 390, + 222, + 601, + 367, + 221, + 411, + 714, + 620, + 966, + 73, + 203, + 631, + 833, + 610, + 487, + 677, + 596 + ] + } + ] + }`, + `{ + "legend": { + "top": "-140", + "data": [ + "Milk Tea", + "Matcha Latte", + "Cheese Cocoa", + "Walnut Brownie" + ] + }, + "padding": [ + 150, + 10, + 10, + 10 + ], + "xAxis": [ + { + "data": [ + "2012", + "2013", + "2014", + "2015", + "2016", + "2017" + ] + } + ], + "series": [ + { + "data": [ + 56.5, + 82.1, + 88.7, + 70.1, + 53.4, + 85.1 + ] + }, + { + "data": [ + 51.1, + 51.4, + 55.1, + 53.3, + 73.8, + 68.7 + ] + }, + { + "data": [ + 40.1, + 62.2, + 69.5, + 36.4, + 45.2, + 32.5 + ] + }, + { + "data": [ + 25.2, + 37.1, + 41.2, + 18, + 33.9, + 49.1 + ] + } + ], + "children": [ + { + "box": { + "left": 0, + "top": 30, + "right": 600, + "bottom": 150 + }, + "legend": { + "show": false + }, + "series": [ + { + "type": "pie", + "radius": "50%", + "data": [ + { + "value": 435.9, + "name": "Milk Tea" + }, + { + "value": 354.3, + "name": "Matcha Latte" + }, + { + "value": 285.9, + "name": "Cheese Cocoa" + }, + { + "value": 204.5, + "name": "Walnut Brownie" + } + ] + } + ] + } + ] + }`, + } + handler(w, req, nil, echartsOptions) } func main() { http.HandleFunc("/", indexHandler) + http.HandleFunc("/echarts", echartsHandler) http.ListenAndServe(":3012", nil) } diff --git a/legend_test.go b/legend_test.go index 2dc286f..c5d7e50 100644 --- a/legend_test.go +++ b/legend_test.go @@ -23,7 +23,6 @@ package charts import ( - "fmt" "testing" "github.com/stretchr/testify/assert" @@ -179,7 +178,6 @@ func TestLegendRender(t *testing.T) { assert.Nil(err) assert.Equal(tt.box, b) data, err := d.Bytes() - fmt.Println(string(data)) assert.Nil(err) assert.NotEmpty(data) assert.Equal(tt.result, string(data)) diff --git a/mark_point_test.go b/mark_point_test.go index 2092bcf..2cd8fdd 100644 --- a/mark_point_test.go +++ b/mark_point_test.go @@ -23,7 +23,6 @@ package charts import ( - "fmt" "testing" "github.com/stretchr/testify/assert" @@ -100,6 +99,5 @@ func TestMarkPointRender(t *testing.T) { }) data, err := d.Bytes() assert.Nil(err) - fmt.Println(string(data)) assert.Equal("\\n51", string(data)) }