package charter import ( "bytes" "encoding/base64" "fmt" "math/rand" "os" "time" "github.com/wcharczuk/go-chart" "github.com/wcharczuk/go-chart/drawing" ) const ( lineChartXAxisName = "Date" lineChartYAxisName = "Count" lineChartHeight = 700 lineChartWidth = 1280 colorMultiplier = 256 imgStrPrefix = "data:image/png;base64," pieLabelFormat = "%v %v" barChartTryAgainErr = "invalid data range; cannot be zero" ) var ( lineChartStyle = chart.Style{ Padding: chart.Box{ Top: 30, Left: 150, }, } defaultChartStyle = chart.Style{ Padding: chart.Box{ Top: 30, }, } timeFormat = chart.TimeDateValueFormatter ) type LineYValue struct { Name string Values []float64 } type ChartValue struct { Name string Value float64 } // createLineChart 创建线性图 func createLineChart(title string, endTime time.Time, values []LineYValue) (img string, err error) { if len(values) == 0 { return } // 1、计算X轴 lenX := len(values[0].Values) // X轴内容xValues 及 X轴坐标ticks var xValues []time.Time var ticks []chart.Tick for i := lenX - 1; i >= 0; i-- { curTime := endTime.AddDate(0, 0, -i) xValues = append(xValues, curTime) ticks = append(ticks, chart.Tick{Value: getNsec(curTime), Label: timeFormat(curTime)}) } // 2、生成Series var series []chart.Series for _, yValue := range values { series = append(series, chart.TimeSeries{ Name: yValue.Name, Style: chart.Style{ // 随机渲染线条颜色 StrokeColor: drawing.Color{ R: uint8(rand.Intn(colorMultiplier)), G: uint8(rand.Intn(colorMultiplier)), B: uint8(rand.Intn(colorMultiplier)), A: uint8(colorMultiplier - 1), // 透明度 }, }, XValues: xValues, YValues: yValue.Values, }) fmt.Println(series) } // 3、新建图形 graph := chart.Chart{ Title: title, Background: lineChartStyle, Width: lineChartWidth, Height: lineChartHeight, XAxis: chart.XAxis{ Name: lineChartXAxisName, ValueFormatter: timeFormat, Ticks: ticks, }, YAxis: chart.YAxis{ Name: lineChartYAxisName, }, Series: series, } graph.Elements = []chart.Renderable{ chart.LegendLeft(&graph), } // 4、输出目标 //img, err = writeLineChart(&graph) img, err = writeLineChartToPng(&graph) return } // getNsec 获取纳秒数 func getNsec(cur time.Time) float64 { return float64(cur.Unix() * int64(time.Second)) } func writeLineChartToPng(c *chart.Chart) (img string, err error) { f, err := os.Create("graph.png") if err !=nil { fmt.Println(err.Error()) } err = c.Render(chart.PNG, f) return } func writeLineChart(c *chart.Chart) (img string, err error) { var imgContent bytes.Buffer err = c.Render(chart.PNG, &imgContent) if err != nil { return } img = imgToStr(imgContent) return } func imgToStr(imgContent bytes.Buffer) string { return imgStrPrefix + base64.StdEncoding.EncodeToString(imgContent.Bytes()) } // createPieChart 创建饼图 func createPieChart(title string, pieValues []ChartValue) (img string, err error) { if len(pieValues) == 0 { return } // 1、构建value var values []chart.Value for _, v := range pieValues { values = append(values, chart.Value{ Value: v.Value, Label: fmt.Sprintf(pieLabelFormat, getSimpleSensType(v.Name), formatValue(v.Value)), }) } // 2、新建饼图 pie := chart.PieChart{ Title: title, Background: defaultChartStyle, Values: values, } // 4、输出目标 img, err = writePieChart(&pie) return } func formatValue(f float64) string { return fmt.Sprintf("%.2fW", f/10000) } func getSimpleSensType(name string) string { if name == "个人数据" { return "Personal" } return "Other" } func writePieChartToPng(c *chart.PieChart) (img string, err error) { f, _ := os.Create("pie.png") err = c.Render(chart.PNG, f) return } func writePieChart(c *chart.PieChart) (img string, err error) { var imgContent bytes.Buffer err = c.Render(chart.PNG, &imgContent) if err != nil { return } img = imgToStr(imgContent) return } // createBarChart 创建柱状图 func createBarChart(title string, barValues []ChartValue) (img string, err error) { if len(barValues) == 0 { return } // 1、构建value var values []chart.Value for _, v := range barValues { values = append(values, chart.Value{ Value: v.Value, Label: v.Name, }) } // 2、新建饼图 bar := chart.BarChart{ XAxis: chart.Style{ TextWrap: 0, // default 1为可以溢出规定的范围 }, Width: 2560, BarWidth: 50, BarSpacing: 300, Title: title, Background: defaultChartStyle, Bars: values, } // 4、输出目标 img, err = writeBarChart(&bar) if err != nil && err.Error() == barChartTryAgainErr { // 添加一个隐藏条目,设置透明度A为0, 设置任意属性如R不为0即可 values = append(values, chart.Value{ Style: chart.Style{ StrokeColor: drawing.Color{R: 1}, }, Value: 0, Label: "", }) bar.Bars = values img, err = writeBarChart(&bar) } return } func writeBarChartToPng(c *chart.BarChart) (img string, err error) { f, _ := os.Create("bar.png") err = c.Render(chart.PNG, f) return } func writeBarChart(c *chart.BarChart) (img string, err error) { var imgContent bytes.Buffer err = c.Render(chart.PNG, &imgContent) if err != nil { return } img = imgToStr(imgContent) return }