From 63f0be79dd87d36a25d67474f8f14ed96b57fed4 Mon Sep 17 00:00:00 2001 From: Zeni Kim Date: Sun, 27 Oct 2024 22:48:01 -0500 Subject: [PATCH] add web server sample --- README.md | 18 ++++++----- examples/bar_chart/output.png | Bin 19152 -> 19146 bytes examples/bar_chart_web/main.go | 55 +++++++++++++++++++++++++++++++++ examples/pie_chart_web/main.go | 55 +++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 8 deletions(-) create mode 100644 examples/bar_chart_web/main.go create mode 100644 examples/pie_chart_web/main.go diff --git a/README.md b/README.md index fb10018..872548b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ go-chart ======== -This project starts from a full copy from [https://github.com/wcharczuk/go-chart](https://github.com/wcharczuk/go-chart). 28 Oct 2024. +This project starts from a full copy from [https://git.smarteching.com/zeni/go-chart](https://git.smarteching.com/zeni/go-chart). 28 Oct 2024. - @@ -12,7 +12,7 @@ Master should now be on the v3.x codebase, which overhauls the api significantly To install `chart` run the following: ```bash -> go get github.com/wcharczuk/go-chart/v2@latest +> go get git.smarteching.com/zeni/go-chart/v2@latest ``` Most of the components are interchangeable so feel free to crib whatever you want. @@ -21,27 +21,27 @@ Most of the components are interchangeable so feel free to crib whatever you wan Spark Lines: -![](https://raw.githubusercontent.com/wcharczuk/go-chart/master/_images/tvix_ltm.png) +![](https://git.smarteching.com/zeni/go-chart/raw/branch/main/_images/tvix_ltm.png) Single axis: -![](https://raw.githubusercontent.com/wcharczuk/go-chart/master/_images/goog_ltm.png) +![](https://git.smarteching.com/zeni/go-chart/raw/branch/main/_images/goog_ltm.png) Two axis: -![](https://raw.githubusercontent.com/wcharczuk/go-chart/master/_images/two_axis.png) +![](https://git.smarteching.com/zeni/go-chart/raw/branch/main/_images/two_axis.png) # Other Chart Types Pie Chart: -![](https://raw.githubusercontent.com/wcharczuk/go-chart/master/_images/pie_chart.png) +![](https://git.smarteching.com/zeni/go-chart/raw/branch/main/_images/pie_chart.png) The code for this chart can be found in `examples/pie_chart/main.go`. Stacked Bar: -![](https://raw.githubusercontent.com/wcharczuk/go-chart/master/_images/stacked_bar.png) +![](https://git.smarteching.com/zeni/go-chart/raw/branch/main/_images/stacked_bar.png) The code for this chart can be found in `examples/stacked_bar/main.go`. @@ -49,6 +49,8 @@ The code for this chart can be found in `examples/stacked_bar/main.go`. Actual chart configurations and examples can be found in the `./examples/` directory. They are simple CLI programs that write to `output.png` (they are also updated with `go generate`. +If folder ends in "web", has web servers, so start them with `go run main.go` then access `http://localhost:8080` to see the output. + # Usage Everything starts with the `chart.Chart` object. The bare minimum to draw a chart would be the following: @@ -59,7 +61,7 @@ import ( ... "bytes" ... - "github.com/wcharczuk/go-chart/v2" //exposes "chart" + "git.smarteching.com/zeni/go-chart/v2" //exposes "chart" ) graph := chart.Chart{ diff --git a/examples/bar_chart/output.png b/examples/bar_chart/output.png index 321a3414e6355cb11c52ec6c30ba7e89147b2c49..840c46e1a1f9bdff7f661450fd796f6167d34163 100644 GIT binary patch literal 19146 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 literal 19152 zcmeIa2{e{(-!6PN3q?hWB8?)Hu`-pUA{jD8Xfl(`Q-+EtNfScIlsT1|P$6YVZeuc3 z$UM*E{Tp1q#;d!N0YckjLS_wBWI>%Sg7ab5Ryo#$^je#dc~?kJr(v4)nFmP8`0 zIdxJ-g+yA8zb+-wEX9|{DR%})B)Py-GDlS%p7k|5sxoOTOb*MZM%}!-ly)7H{iWr1 zWDdMsCc8u<@=lh=(@iDHk57Nx^@xl0G?VbhILmsO^S4j#zejfdtJYbOXx+O*Gw`%iDO9Gw2m}|~ewGbmA)+PAxBkW8w?D$G@r)(u2 zhO})5@o1zYvNXgO_j`=Q7t&@<>K6fN>X$1X)GwcCh&zxTtlQwiKwKEB7@qGko5A>@ zy1Kf!_;_pK64IgV_OKR?Ch99v5Jy7~LRe*Kbgo=`Os5*4**%CdaC zTVc!At>eN8JQ^>f@#n=0EiEk()4C*u5Rv}I^hBkN8#ZiUVcFv`H8)zhnnZfeg2%M7 zpBd{;DOi}<>(kuaJkCzCvbOI05~^KWC1T#Ve8r0C*;xv|m(4&^_Jaox#>U2I`}3S9 z!z5jtqGWv+0&guLsrng`Nbk0t4wsy-6*zFWPZESCwrZ?tR!t(i%onWCM6}s&z~~F zYyG=C+ot;wq;;MJ~6 zHB>Y-?38jQvGD7j&#{S5>+kFoH7I}jyCS6Zt)q2in8fSXuNgQb%Rhf!O-EN49*g(YxiyjTAFRx!IR2e18je)N`*KA-N}DJdF~ ze89ekA}i@PF|x99o9E`_oOyQewPLtr)Cs?h($5ZB{wfa=Ov#_=376PJdRM&-tCRXY z-BjcH^*MhYjeEYn+UX{>@n>T>kKNw1d9xaqm|b7P{jFkTGI?ZVBv{Cp{6@b_IZF1> zp+l!m96NT*$Hym~Vf%>_C&I-Y$)7(PkF{mC%F9n{E2*dmSpPoFDU;_kE;&C|Eo@r%Ox#g`pWmYJ_L?

a_y($LV)LT_(x9~SABBIxhmo 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%0DT62jW`lyy3%A#ZK19p)(!^+=@^<9z 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 diff --git a/examples/bar_chart_web/main.go b/examples/bar_chart_web/main.go new file mode 100644 index 0000000..714276e --- /dev/null +++ b/examples/bar_chart_web/main.go @@ -0,0 +1,55 @@ +package main + +//go:generate go run main.go + +import ( + "fmt" + "log" + "net/http" + "os" + + "git.smarteching.com/zeni/go-chart/v2" +) + +func drawChart(res http.ResponseWriter, req *http.Request) { + graph := chart.BarChart{ + Title: "Test Bar Chart", + Background: chart.Style{ + Padding: chart.Box{ + Top: 40, + }, + }, + Height: 512, + BarWidth: 60, + Bars: []chart.Value{ + {Value: 5.25, Label: "Blue"}, + {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 := graph.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 "8080" +} + +func main() { + listenPort := fmt.Sprintf(":%s", port()) + fmt.Printf("Listening on %s\n", listenPort) + http.HandleFunc("/", drawChart) + log.Fatal(http.ListenAndServe(listenPort, nil)) +} diff --git a/examples/pie_chart_web/main.go b/examples/pie_chart_web/main.go new file mode 100644 index 0000000..fa25594 --- /dev/null +++ b/examples/pie_chart_web/main.go @@ -0,0 +1,55 @@ +package main + +import ( + "fmt" + "log" + "net/http" + + "git.smarteching.com/zeni/go-chart/v2" +) + +func drawChart(res http.ResponseWriter, req *http.Request) { + pie := chart.PieChart{ + Width: 512, + Height: 512, + Values: []chart.Value{ + {Value: 5, Label: "Blue"}, + {Value: 5, Label: "Green"}, + {Value: 4, Label: "Gray"}, + {Value: 4, Label: "Orange"}, + {Value: 3, Label: "Deep Blue"}, + {Value: 3, Label: "??"}, + {Value: 1, Label: "!!"}, + }, + } + + res.Header().Set("Content-Type", "image/png") + err := pie.Render(chart.PNG, res) + if err != nil { + fmt.Printf("Error rendering pie chart: %v\n", err) + } +} + +func drawChartRegression(res http.ResponseWriter, req *http.Request) { + pie := chart.PieChart{ + Width: 512, + Height: 512, + Values: []chart.Value{ + {Value: 5, Label: "Blue"}, + {Value: 2, Label: "Two"}, + {Value: 1, Label: "One"}, + }, + } + + res.Header().Set("Content-Type", chart.ContentTypeSVG) + err := pie.Render(chart.SVG, res) + if err != nil { + fmt.Printf("Error rendering pie chart: %v\n", err) + } +} + +func main() { + http.HandleFunc("/", drawChart) + http.HandleFunc("/reg", drawChartRegression) + log.Fatal(http.ListenAndServe(":8080", nil)) +}