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你可以完全参考里面实现你的需求

image.png image.png

总结:
以上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))
}

image.png
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))
}

上一篇 下一篇

猜你喜欢

热点阅读