golang 图表组件整理
2020-07-17 本文已影响0人
Best博客
前沿
js有很强大的图表组件,但go弄起来其实也挺方便的,毕竟或许你跟我一样懒得切换js视角再去了解了
chromedp/chromedp
这个组件调用的是chrome浏览器的api去做到你给它一个url,它帮你截屏该url的各个元素渲染后的图片。简单好用,还清晰,但是需要你本地装了浏览器噢,当然该组件提供docker最小集成依赖方案。
package main
import (
"context"
"io/ioutil"
"log"
cdp "github.com/chromedp/chromedp"
)
// 此处以360搜索首页为例
const urlstr = `https://www.so.com/`
// 需要截图的元素,支持CSS selector以及XPath query
const selector = `#main`
func main() {
// 创建新的cdp上下文
ctx, cancel := cdp.NewContext(context.Background())
defer cancel()
var buf []byte
if err := cdp.Run(ctx, elementScreenshot(urlstr, selector, &buf)); err != nil {
log.Fatal(err)
}
// 写入文件
if err := ioutil.WriteFile("360_so.png", buf, 0644); err != nil {
log.Fatal(err)
}
}
// 截图方法
func elementScreenshot(urlstr, sel string, res *[]byte) cdp.Tasks {
return cdp.Tasks{
// 打开url指向的页面
cdp.Navigate(urlstr),
// 等待待截图的元素渲染完成
cdp.WaitVisible(sel, cdp.ByID),
// 也可以等待一定的时间
//cdp.Sleep(time.Duration(3) * time.Second),
// 执行截图
cdp.Screenshot(sel, res, cdp.NodeVisible, cdp.ByID),
}
}
go-echarts/go-echarts
这个组件能很轻松的帮我们直接生成各种很漂亮的图表,柱形图,折线图的html静态页面。原理是后台组装好数据后渲染成html与js实体,浏览器解析成漂亮的图表,但其本质是html页面并非图片。优势是可以很轻松的做到各式各样的漂亮图表,但并不能直接生成图片或者pdf这样子的资源。在组件下的_examples有很多demo你可以完全参考里面实现你的需求


总结:
以上2个组件一个是用来以浏览器的身份可以截屏任意url渲染后的页面图片的,一个是以html的方式做到生成各式各样的漂亮页面的,2者结合在一起就能打出一套组合拳,帮助你很轻松的生成各式各样的漂亮图表图片。
wcharczuk/go-chart
这个组件能够自己直接一次性生成一定种类的图表图片,并以http方式对外提供服务,但是生成的图表丰富度是没上面的 # go-echarts/go-echarts丰富的。优点是依赖少,用起来也简单,支持一定量的图表(比如柱状)。刚好最符合我发送将数据图表化后邮件发送的需求,这是个小需求需要的是快速使用,依赖越少越好,图表种类有符合我的柱状图,对外直接http提供服务
字体下载地址
或者你直接百度:Microsoft-YaHei.ttf
package main
import (
"fmt"
"github.com/golang/freetype/truetype"
"io/ioutil"
"log"
"net/http"
"os"
"github.com/wcharczuk/go-chart"
)
//填你字体库路径,因为这个库自带的字体不支持中文你需要自己去下一个
const fontFile := "/Users/hushuang/Downloads/Microsoft-YaHei.ttf"
// getZWFont 加载字体
func getZWFont() *truetype.Font {
// 读字体数据
fontBytes, err := ioutil.ReadFile(fontFile)
if err != nil {
log.Println(err)
return nil
}
font, err := truetype.Parse(fontBytes)
if err != nil {
log.Println(err)
return nil
}
return font
}
func drawChart(res http.ResponseWriter, req *http.Request) {
f := getZWFont() // 用自己的字体
sbc := chart.BarChart{
Title: "login是的",
TitleStyle: chart.StyleShow(),
Font: f,
Background: chart.Style{
Padding: chart.Box{
Top: 40,
},
},
Height: 812,
BarWidth: 60,
XAxis: chart.Style{
Show: true,
},
YAxis: chart.YAxis{
Style: chart.Style{
Show: true,
},
},
Bars: []chart.Value{
{Value: 5.25, Label: "2020-10-22"},
{Value: 4.88, Label: "Green"},
{Value: 4.74, Label: "Gray"},
{Value: 3.22, Label: "Orange"},
{Value: 3, Label: "Test"},
{Value: 2.27, Label: "??"},
{Value: 1, Label: "!!"},
},
}
res.Header().Set("Content-Type", "image/png")
err := sbc.Render(chart.PNG, res)
if err != nil {
fmt.Printf("Error rendering chart: %v\n", err)
}
}
func port() string {
if len(os.Getenv("PORT")) > 0 {
return os.Getenv("PORT")
}
return "8081"
}
func main() {
listenPort := fmt.Sprintf(":%s", port())
fmt.Printf("Listening on %s\n", listenPort)
http.HandleFunc("/", drawChart)
log.Fatal(http.ListenAndServe(listenPort, nil))
}

package main
import (
"fmt"
"github.com/golang/freetype/truetype"
"io/ioutil"
"log"
"net/http"
"os"
"github.com/wcharczuk/go-chart"
)
// getZWFont 加载字体
func getZWFont() *truetype.Font {
fontFile := "/Users/hushuang/Downloads/Microsoft-YaHei.ttf"
//fontFile := "/Library/Fonts/AppleMyungjo.ttf"
// 读字体数据
fontBytes, err := ioutil.ReadFile(fontFile)
if err != nil {
log.Println(err)
return nil
}
font, err := truetype.Parse(fontBytes)
if err != nil {
log.Println(err)
return nil
}
return font
}
func drawChart(res http.ResponseWriter, req *http.Request) {
bars := []chart.Value{
{Value: 5.25, Label: "2020-10-22"},
{Value: 4.88, Label: "Green"},
{Value: 4.74, Label: "Gray"},
{Value: 3.22, Label: "Orange"},
{Value: 3, Label: "Test"},
{Value: 2.27, Label: "??"},
{Value: 1, Label: "!!"},
}
sbc := generateImg(bars)
res.Header().Set("Content-Type", "image/png")
err := sbc.Render(chart.PNG, res)
if err != nil {
fmt.Printf("Error rendering chart: %v\n", err)
}
}
/*
[]chart.Value{
{Value: 5.25, Label: "2020-10-22"},
{Value: 4.88, Label: "Green"},
{Value: 4.74, Label: "Gray"},
{Value: 3.22, Label: "Orange"},
{Value: 3, Label: "Test"},
{Value: 2.27, Label: "??"},
{Value: 1, Label: "!!"},
}
*/
func generateImg(bars []chart.Value)(sbc *chart.BarChart){
sbc = &chart.BarChart{
TitleStyle: chart.StyleShow(),
Background: chart.Style{
Padding: chart.Box{
Top: 40,
},
},
Height: 812,
BarWidth: 60,
XAxis: chart.Style{
Show: true,
},
YAxis: chart.YAxis{
Style: chart.Style{
Show: true,
},
},
Bars: bars,
}
return sbc
}
func port() string {
if len(os.Getenv("PORT")) > 0 {
return os.Getenv("PORT")
}
return "8081"
}
func main() {
listenPort := fmt.Sprintf(":%s", port())
fmt.Printf("Listening on %s\n", listenPort)
http.HandleFunc("/", drawChart)
log.Fatal(http.ListenAndServe(listenPort, nil))
}