phantomjs技巧之golang後端生成highcharts圖片檔案

葛平發表於2017-03-30

需求

專案要求為每一個阿里雲大客戶每週生成一份週報,週報內容包括各類雲產品(如ECS/SLB/RDS/CDN)使用情況。我們知道通過前端js可以將highcharts曲線圖/餅圖等轉換成圖片格式,但是隻能線上convert,也就是圖片需要上傳到highcharts伺服器,資料安全肯定無法保證,所以本文藉助phantomjs這個利器來直接通過服務端生成圖片

highcharts配置項結構體定義

1. 曲線圖定義

//series結構體定義
type Series struct {
        Data          [][]interface{} `json:"data"`
        Name          string          `json:"name"`
        PointInterval int             `json:"pointInterval"`
}

//chart配置結構體定義
type ChartOption struct {
        Title struct {
                Margin int `json:"margin"`
                Style  struct {
                        FontSize   string `json:"fontSize"`
                        FontWeight string `json:"fontWeight"`
                } `json:"style"`
                Text string `json:"text"`
                X    int    `json:"x"`
        } `json:"title"`

        Chart struct {
                Type            string `json:"type"`
                BackgroundColor string `json:"backgroundColor"`
        } `json:"chart"`

        Credits struct {
                Enabled bool `json:"enabled"`
        } `json:"credits"`

        XAxis struct {
                Type                 string `json:"type"`
                DateTimeLabelFormats struct {
                        Day string `json:"day"`
                } `json:"dateTimeLabelFormats"`
                TickInterval int `json:"tickInterval"`
        } `json:"xAxis"`
        YAxis struct {
                Labels struct {
                        Format string `json:"format"`
                        Style  struct {
                                FontSize   string `json:"fontSize"`
                                FontWeight string `json:"fontWeight"`
                        } `json:"style"`
                } `json:"labels"`
                Title struct {
                        Text string `json:"text"`
                } `json:"title"`
        } `json:"yAxis"`

        PlotOptions struct {
                Line struct {
                        DataLabels struct {
                                Enabled bool `json:"enabled"`
                        } `json:"dataLabels"`
                } `json:"line"`
        } `json:"plotOptions"`

        Series []Series `json:"series"`

        Exporting struct {
                SourceWidth  int `json:"sourceWidth"`
                SourceHeight int `json:"sourceHeight"`
                Scale        int `json:"scale"`
        } `json:"exporting"`
}

2. 餅圖定義

type PieOption struct {
        Chart struct {
                BackgroundColor string `json:"backgroundColor"`
        } `json:"chart"`
        Colors  []string `json:"colors"`
        Credits struct {
                Enabled bool `json:"enabled"`
        } `json:"credits"`
        PlotOptions struct {
                Pie struct {
                        DataLabels struct {
                                Format string `json:"format"`
                        } `json:"dataLabels"`
                } `json:"pie"`
        } `json:"plotOptions"`
        Series [1]struct {
                Data       [][]interface{} `json:"data"`
                DataLabels struct {
                        Style struct {
                                FontSize   string `json:"fontSize"`
                                FontWeight string `json:"fontWeight"`
                        } `json:"style"`
                } `json:"dataLabels"`
                Type string `json:"type"`
        } `json:"series"`
        Title struct {
                Margin int `json:"margin"`
                Style  struct {
                        FontSize   string `json:"fontSize"`
                        FontWeight string `json:"fontWeight"`
                } `json:"style"`
                Text string `json:"text"`
        } `json:"title"`
}

初始化highchart配置

1. 曲線圖配置初始化(sample)

func NewChartOption() ChartOption {

        cht := ChartOption{}

        cht.Title.Margin = 30
        cht.Title.Style.FontSize = "18px"
        cht.Title.Style.FontWeight = "bold"
        cht.Title.X = -20

        cht.Chart.Type = "line"
        cht.Chart.BackgroundColor = "#f5f5f5"
        cht.Credits.Enabled = false

        cht.XAxis.Type = "datetime"
        cht.XAxis.DateTimeLabelFormats.Day = "%m月/%d日"
        cht.YAxis.Labels.Style.FontSize = "14px"
        cht.YAxis.Labels.Style.FontWeight = "bold"

        cht.PlotOptions.Line.DataLabels.Enabled = false

        cht.Exporting.Scale = 1
        cht.Exporting.SourceHeight = 400  //圖片高度
        cht.Exporting.SourceWidth = 600   //圖片寬度

        return cht
}

2. 餅圖配置初始化(sample)

func NewPieOption() PieOption {
        pie := PieOption{}

        pie.Title.Margin = 30
        pie.Title.Style.FontSize = "18px"
        pie.Title.Style.FontWeight = "bold"

        pie.Credits.Enabled = false
        pie.Colors = []string{"#0067cc", "#30bfff", "#02fdff", "#4ad1d1", "#00b4cc", "#0193cd"} //餅圖顏色
        pie.Chart.BackgroundColor = "#f5f5f5" //背景顏色
        pie.Series[0].Type = "pie"
        pie.Series[0].DataLabels.Style.FontSize = "14px"
        pie.Series[0].DataLabels.Style.FontWeight = "bold"

        return pie
}

highcharts外掛

  1. 外掛下載:https://github.com/pesla/highcharts-phantomjs
  2. 安裝phantomjs或者直接下載二進位制bin檔案
  3. 資料載入到highcharts以及後端生成圖片程式碼
        chartoption := NewChartOption()
        chartoption.Title.Text = "xxx"
        chartoption.YAxis.Labels.Format = "{value}"
        chartoption.XAxis.TickInterval = 24 * 3600 * 1000 //天粒度
        chartoption.Exporting.SourceWidth = 1200 //寬度
        chartoption.PlotOptions.Line.DataLabels.Enabled = true //無水印
        chartoption.XAxis.DateTimeLabelFormats.Day = "%Y/%m/%d" //日期格式

        var inputData [][]interface{}
        for _, v := range data {
                inputData = append(inputData, []interface{}{v.Timestamp * 1000, v.Rate})
        }
        chartoption.Series = append(chartoption.Series, common.Series{Name: "xxx", Data: inputData, PointInterval: 24 * 3600 * 1000})
        chartBytes, _ := json.Marshal(chartoption)

        optionjson := "test.json"
        f, _ := os.Create(optionjson)
        defer os.Remove(f.Name())
        f.Write(chartBytes) //將配置寫入json檔案
        png := "out.png" //輸出圖片名
        cmd := exec.Command("./phantomjs", "/highcharts/js/highcharts-convert.js", "-infile", optionjson, "-outfile", png)
        cmd.Stdout = os.Stdout
        cmd.Run()
}

## 結語
自從有了phantomjs,再也不用擔心後端幹不了前端的活了。。。


相關文章