package main import ( "bytes" "net/http" "strconv" charts "github.com/vicanso/go-charts" "github.com/wcharczuk/go-chart/v2" "github.com/wcharczuk/go-chart/v2/drawing" ) var html = ` go-charts
{{body}}
` 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() theme := query.Get("theme") width, _ := strconv.Atoi(query.Get("width")) 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{ // 普通折线图 { Title: charts.TitleOption{ Text: "Line", }, Legend: charts.NewLegendOption([]string{ "Email", "Union Ads", "Video Ads", "Direct", "Search Engine", }), XAxis: charts.NewXAxisOption([]string{ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", }), SeriesList: []charts.Series{ charts.NewSeriesFromValues([]float64{ 120, 132, 101, 134, 90, 230, 210, }), charts.NewSeriesFromValues([]float64{ 220, 182, 191, 234, 290, 330, 310, }), charts.NewSeriesFromValues([]float64{ 150, 232, 201, 154, 190, 330, 410, }), charts.NewSeriesFromValues([]float64{ 320, 332, 301, 334, 390, 330, 320, }), charts.NewSeriesFromValues([]float64{ 820, 932, 901, 934, 1290, 1330, 1320, }), }, }, // 温度折线图 { Title: charts.TitleOption{ Text: "Temperature Change in the Coming Week", }, Padding: chart.Box{ Top: 20, Left: 20, Right: 30, Bottom: 20, }, Legend: charts.NewLegendOption([]string{ "Highest", "Lowest", }, charts.PositionRight), XAxis: charts.NewXAxisOption([]string{ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", }, charts.FalseFlag()), SeriesList: []charts.Series{ { Data: charts.NewSeriesDataFromValues([]float64{ 14, 11, 13, 11, 12, 12, 7, }), MarkPoint: charts.NewMarkPoint(charts.SeriesMarkDataTypeMax, charts.SeriesMarkDataTypeMin), MarkLine: charts.NewMarkLine(charts.SeriesMarkDataTypeAverage), }, { Data: charts.NewSeriesDataFromValues([]float64{ 1, -2, 2, 5, 3, 2, 0, }), MarkLine: charts.NewMarkLine(charts.SeriesMarkDataTypeAverage), }, }, }, // 柱状图 { Title: charts.TitleOption{ Text: "Bar", }, XAxis: charts.NewXAxisOption([]string{ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", }), Legend: charts.LegendOption{ Data: []string{ "Rainfall", "Evaporation", }, Icon: charts.LegendIconRect, }, SeriesList: []charts.Series{ charts.NewSeriesFromValues([]float64{ 120, 200, 150, 80, 70, 110, 130, }, charts.ChartTypeBar), { Type: charts.ChartTypeBar, Data: []charts.SeriesData{ { Value: 100, }, { Value: 190, Style: chart.Style{ FillColor: drawing.Color{ R: 169, G: 0, B: 0, A: 255, }, }, }, { Value: 230, }, { Value: 140, }, { Value: 100, }, { Value: 200, }, { Value: 180, }, }, }, }, }, // 柱状图+mark { Title: charts.TitleOption{ Text: "Rainfall vs Evaporation", Subtext: "Fake Data", }, Padding: chart.Box{ Top: 20, Right: 20, Bottom: 20, Left: 20, }, XAxis: charts.NewXAxisOption([]string{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", }), Legend: charts.NewLegendOption([]string{ "Rainfall", "Evaporation", }, charts.PositionRight), SeriesList: []charts.Series{ { Type: charts.ChartTypeBar, Data: charts.NewSeriesDataFromValues([]float64{ 2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3, }), MarkPoint: charts.NewMarkPoint( charts.SeriesMarkDataTypeMax, charts.SeriesMarkDataTypeMin, ), MarkLine: charts.NewMarkLine( charts.SeriesMarkDataTypeAverage, ), }, { Type: charts.ChartTypeBar, Data: charts.NewSeriesDataFromValues([]float64{ 2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3, }), MarkPoint: charts.NewMarkPoint( charts.SeriesMarkDataTypeMax, charts.SeriesMarkDataTypeMin, ), MarkLine: charts.NewMarkLine( charts.SeriesMarkDataTypeAverage, ), }, }, }, // 双Y轴示例 { XAxis: charts.NewXAxisOption([]string{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", }), Legend: charts.NewLegendOption([]string{ "Evaporation", "Precipitation", "Temperature", }), YAxisList: []charts.YAxisOption{ { Formatter: "{value}°C", Color: drawing.Color{ R: 250, G: 200, B: 88, A: 255, }, }, { Formatter: "{value}ml", Color: drawing.Color{ R: 84, G: 112, B: 198, A: 255, }, }, }, SeriesList: []charts.Series{ { Type: charts.ChartTypeBar, Data: charts.NewSeriesDataFromValues([]float64{ 2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3, 10.2, }), YAxisIndex: 1, }, { Type: charts.ChartTypeBar, Data: charts.NewSeriesDataFromValues([]float64{ 2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3, 20.2, }), YAxisIndex: 1, }, { Data: charts.NewSeriesDataFromValues([]float64{ 2.0, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3, 23.4, 23.0, 16.5, 12.0, 6.2, 30.3, }), }, }, }, // 饼图 { Title: charts.TitleOption{ Text: "Referer of a Website", Subtext: "Fake Data", Left: charts.PositionCenter, }, Legend: charts.LegendOption{ Orient: charts.OrientVertical, Data: []string{ "Search Engine", "Direct", "Email", "Union Ads", "Video Ads", }, Left: charts.PositionLeft, }, SeriesList: charts.NewPieSeriesList([]float64{ 1048, 735, 580, 484, 300, }, charts.PieSeriesOption{ Label: charts.SeriesLabel{ Show: true, }, Radius: "35%", }), }, // 雷达图 { Title: charts.TitleOption{ Text: "Basic Radar Chart", }, Legend: charts.NewLegendOption([]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, }), }, }, }, // 漏斗图 { Title: charts.TitleOption{ Text: "Funnel", }, Legend: charts.NewLegendOption([]string{ "Show", "Click", "Visit", "Inquiry", "Order", }), SeriesList: []charts.Series{ { 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, }), }, { Type: charts.ChartTypeFunnel, Name: "Click", Data: charts.NewSeriesDataFromValues([]float64{ 80, }), }, { Type: charts.ChartTypeFunnel, Name: "Show", Data: charts.NewSeriesDataFromValues([]float64{ 100, }), }, }, }, // 多图展示 { Legend: charts.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: charts.NewXAxisOption([]string{ "2012", "2013", "2014", "2015", "2016", "2017", }), YAxisList: []charts.YAxisOption{ { Min: charts.NewFloatPoint(0), Max: charts.NewFloatPoint(90), }, }, SeriesList: []charts.Series{ charts.NewSeriesFromValues([]float64{ 56.5, 82.1, 88.7, 70.1, 53.4, 85.1, }), charts.NewSeriesFromValues([]float64{ 51.1, 51.4, 55.1, 53.3, 73.8, 68.7, }), charts.NewSeriesFromValues([]float64{ 40.1, 62.2, 69.5, 36.4, 45.2, 32.5, }, charts.ChartTypeBar), charts.NewSeriesFromValues([]float64{ 25.2, 37.1, 41.2, 18, 33.9, 49.1, }, charts.ChartTypeBar), }, Children: []charts.ChartOption{ { Legend: charts.LegendOption{ Show: charts.FalseFlag(), Data: []string{ "Milk Tea", "Matcha Latte", "Cheese Cocoa", "Walnut Brownie", }, }, Box: chart.Box{ Top: 20, Left: 400, Right: 500, Bottom: 120, }, SeriesList: charts.NewPieSeriesList([]float64{ 435.9, 354.3, 285.9, 204.5, }, charts.PieSeriesOption{ Label: charts.SeriesLabel{ Show: true, }, Radius: "35%", }), }, }, }, } 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 ] } ] }`, `{ "title": { "text": "Basic Radar Chart" }, "legend": { "data": [ "Allocated Budget", "Actual Spending" ] }, "radar": { "indicator": [ { "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 } ] }, "series": [ { "name": "Budget vs spending", "type": "radar", "data": [ { "value": [ 4200, 3000, 20000, 35000, 50000, 18000 ], "name": "Allocated Budget" }, { "value": [ 5000, 14000, 28000, 26000, 42000, 21000 ], "name": "Actual Spending" } ] } ] }`, `{ "title": { "text": "Funnel" }, "tooltip": { "trigger": "item", "formatter": "{a}
{b} : {c}%" }, "toolbox": { "feature": { "dataView": { "readOnly": false }, "restore": {}, "saveAsImage": {} } }, "legend": { "data": [ "Show", "Click", "Visit", "Inquiry", "Order" ] }, "series": [ { "name": "Funnel", "type": "funnel", "left": "10%", "top": 60, "bottom": 60, "width": "80%", "min": 0, "max": 100, "minSize": "0%", "maxSize": "100%", "sort": "descending", "gap": 2, "label": { "show": true, "position": "inside" }, "labelLine": { "length": 10, "lineStyle": { "width": 1, "type": "solid" } }, "itemStyle": { "borderColor": "#fff", "borderWidth": 1 }, "emphasis": { "label": { "fontSize": 20 } }, "data": [ { "value": 60, "name": "Visit" }, { "value": 40, "name": "Inquiry" }, { "value": 20, "name": "Order" }, { "value": 80, "name": "Click" }, { "value": 100, "name": "Show" } ] } ] }`, `{ "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) }