diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index f591a3a..ce56fe7 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -14,14 +14,12 @@ jobs:
strategy:
matrix:
go:
+ - '1.22'
+ - '1.21'
- '1.20'
- '1.19'
- '1.18'
- '1.17'
- - '1.16'
- - '1.15'
- - '1.14'
- - '1.13'
steps:
- name: Go ${{ matrix.go }} test
diff --git a/README.md b/README.md
index 1e4ea8b..0650395 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
# go-charts
+Clone from https://github.com/vicanso/go-charts
+
[](https://github.com/vicanso/go-charts/blob/master/LICENSE)
[](https://github.com/vicanso/go-charts/actions)
@@ -33,7 +35,7 @@ More examples can be found in the [./examples/](./examples/) directory.
package main
import (
- charts "github.com/vicanso/go-charts/v2"
+ charts "git.smarteching.com/zeni/go-charts/v2"
)
func main() {
@@ -99,7 +101,7 @@ func main() {
package main
import (
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func main() {
@@ -174,7 +176,7 @@ func main() {
package main
import (
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func main() {
@@ -231,7 +233,7 @@ func main() {
package main
import (
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func main() {
@@ -286,7 +288,7 @@ func main() {
package main
import (
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func main() {
@@ -344,7 +346,7 @@ func main() {
package main
import (
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func main() {
@@ -384,7 +386,7 @@ func main() {
package main
import (
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func main() {
@@ -449,7 +451,7 @@ func main() {
package main
import (
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func main() {
diff --git a/README_zh.md b/README_zh.md
index c31cf77..3f35b97 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -32,7 +32,7 @@
package main
import (
- charts "github.com/vicanso/go-charts/v2"
+ charts "git.smarteching.com/zeni/go-charts/v2"
)
func main() {
@@ -98,7 +98,7 @@ func main() {
package main
import (
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func main() {
@@ -173,7 +173,7 @@ func main() {
package main
import (
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func main() {
@@ -230,7 +230,7 @@ func main() {
package main
import (
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func main() {
@@ -285,7 +285,7 @@ func main() {
package main
import (
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func main() {
@@ -343,7 +343,7 @@ func main() {
package main
import (
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func main() {
@@ -383,7 +383,7 @@ func main() {
package main
import (
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func main() {
@@ -447,7 +447,7 @@ func main() {
package main
import (
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func main() {
diff --git a/alias.go b/alias.go
index a96f50b..edf0dec 100644
--- a/alias.go
+++ b/alias.go
@@ -23,8 +23,8 @@
package charts
import (
- "github.com/wcharczuk/go-chart/v2"
- "github.com/wcharczuk/go-chart/v2/drawing"
+ "git.smarteching.com/zeni/go-chart/v2"
+ "git.smarteching.com/zeni/go-chart/v2/drawing"
)
type Box = chart.Box
diff --git a/axis.go b/axis.go
index 762a6a2..55fa219 100644
--- a/axis.go
+++ b/axis.go
@@ -26,7 +26,7 @@ import (
"strings"
"github.com/golang/freetype/truetype"
- "github.com/wcharczuk/go-chart/v2"
+ "git.smarteching.com/zeni/go-chart/v2"
)
type axisPainter struct {
diff --git a/axis_test.go b/axis_test.go
index d0cff41..85e18ca 100644
--- a/axis_test.go
+++ b/axis_test.go
@@ -26,7 +26,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
- "github.com/wcharczuk/go-chart/v2/drawing"
+ "git.smarteching.com/zeni/go-chart/v2/drawing"
)
func TestAxis(t *testing.T) {
diff --git a/bar_chart.go b/bar_chart.go
index efeb465..043e044 100644
--- a/bar_chart.go
+++ b/bar_chart.go
@@ -26,7 +26,7 @@ import (
"math"
"github.com/golang/freetype/truetype"
- "github.com/wcharczuk/go-chart/v2"
+ "git.smarteching.com/zeni/go-chart/v2"
)
type barChart struct {
@@ -63,6 +63,8 @@ type BarChartOption struct {
// The legend option
Legend LegendOption
BarWidth int
+ // Margin of bar
+ BarMargin int
}
func (b *barChart) render(result *defaultRenderResult, seriesList SeriesList) (Box, error) {
@@ -88,6 +90,9 @@ func (b *barChart) render(result *defaultRenderResult, seriesList SeriesList) (B
margin = 5
barMargin = 3
}
+ if opt.BarMargin > 0 {
+ barMargin = opt.BarMargin
+ }
seriesCount := len(seriesList)
// 总的宽度-两个margin-(总数-1)的barMargin
barWidth := (width - 2*margin - barMargin*(seriesCount-1)) / seriesCount
@@ -142,14 +147,25 @@ func (b *barChart) render(result *defaultRenderResult, seriesList SeriesList) (B
}
top := barMaxHeight - h
- seriesPainter.OverrideDrawingStyle(Style{
- FillColor: fillColor,
- }).Rect(chart.Box{
- Top: top,
- Left: x,
- Right: x + barWidth,
- Bottom: barMaxHeight - 1,
- })
+ if series.RoundRadius <= 0 {
+ seriesPainter.OverrideDrawingStyle(Style{
+ FillColor: fillColor,
+ }).Rect(chart.Box{
+ Top: top,
+ Left: x,
+ Right: x + barWidth,
+ Bottom: barMaxHeight - 1,
+ })
+ } else {
+ seriesPainter.OverrideDrawingStyle(Style{
+ FillColor: fillColor,
+ }).RoundedRect(chart.Box{
+ Top: top,
+ Left: x,
+ Right: x + barWidth,
+ Bottom: barMaxHeight - 1,
+ }, series.RoundRadius)
+ }
// 用于生成marker point
points[j] = Point{
// 居中的位置
diff --git a/bar_chart_test.go b/bar_chart_test.go
index e1522d6..654c320 100644
--- a/bar_chart_test.go
+++ b/bar_chart_test.go
@@ -104,6 +104,76 @@ func TestBarChart(t *testing.T) {
},
result: "",
},
+ {
+ render: func(p *Painter) ([]byte, error) {
+ seriesList := NewSeriesListDataFromValues([][]float64{
+ {
+ 2.0,
+ 4.9,
+ 7.0,
+ 23.2,
+ 25.6,
+ 76.7,
+ 135.6,
+ 162.2,
+ 32.6,
+ 20.0,
+ 6.4,
+ 3.3,
+ },
+ {
+ 2.6,
+ 5.9,
+ 9.0,
+ 26.4,
+ 28.7,
+ 70.7,
+ 175.6,
+ 182.2,
+ 48.7,
+ 18.8,
+ 6.0,
+ 2.3,
+ },
+ })
+ for index := range seriesList {
+ seriesList[index].Label.Show = true
+ seriesList[index].RoundRadius = 5
+ }
+ _, err := NewBarChart(p, BarChartOption{
+ Padding: Box{
+ Left: 10,
+ Top: 10,
+ Right: 10,
+ Bottom: 10,
+ },
+ SeriesList: seriesList,
+ XAxis: NewXAxisOption([]string{
+ "Jan",
+ "Feb",
+ "Mar",
+ "Apr",
+ "May",
+ "Jun",
+ "Jul",
+ "Aug",
+ "Sep",
+ "Oct",
+ "Nov",
+ "Dec",
+ }),
+ YAxisOptions: NewYAxisOptions([]string{
+ "Rainfall",
+ "Evaporation",
+ }),
+ }).Render()
+ if err != nil {
+ return nil, err
+ }
+ return p.Bytes()
+ },
+ result: "",
+ },
}
for _, tt := range tests {
diff --git a/chart_option.go b/chart_option.go
index 5311d50..d80a383 100644
--- a/chart_option.go
+++ b/chart_option.go
@@ -67,6 +67,8 @@ type ChartOption struct {
LineStrokeWidth float64
// The bar with of bar chart
BarWidth int
+ // The margin of each bar
+ BarMargin int
// The bar height of horizontal bar chart
BarHeight int
// Fill the area of line chart
diff --git a/chart_option_test.go b/chart_option_test.go
index ff17750..c354b26 100644
--- a/chart_option_test.go
+++ b/chart_option_test.go
@@ -26,7 +26,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
- "github.com/wcharczuk/go-chart/v2/drawing"
+ "git.smarteching.com/zeni/go-chart/v2/drawing"
)
func TestChartOption(t *testing.T) {
diff --git a/charts.go b/charts.go
index 74db733..31df11c 100644
--- a/charts.go
+++ b/charts.go
@@ -27,7 +27,7 @@ import (
"math"
"sort"
- "github.com/wcharczuk/go-chart/v2"
+ "git.smarteching.com/zeni/go-chart/v2"
)
const labelFontSize = 10
@@ -375,10 +375,11 @@ func Render(opt ChartOption, opts ...OptionFunc) (*Painter, error) {
if len(barSeriesList) != 0 {
handler.Add(func() error {
_, err := NewBarChart(p, BarChartOption{
- Theme: opt.theme,
- Font: opt.font,
- XAxis: opt.XAxis,
- BarWidth: opt.BarWidth,
+ Theme: opt.theme,
+ Font: opt.font,
+ XAxis: opt.XAxis,
+ BarWidth: opt.BarWidth,
+ BarMargin: opt.BarMargin,
}).render(renderResult, barSeriesList)
return err
})
@@ -391,6 +392,7 @@ func Render(opt ChartOption, opts ...OptionFunc) (*Painter, error) {
Theme: opt.theme,
Font: opt.font,
BarHeight: opt.BarHeight,
+ BarMargin: opt.BarMargin,
YAxisOptions: opt.YAxisOptions,
}).render(renderResult, horizontalBarSeriesList)
return err
diff --git a/charts_test.go b/charts_test.go
index da75ee5..bd581e9 100644
--- a/charts_test.go
+++ b/charts_test.go
@@ -26,7 +26,7 @@ import (
"errors"
"testing"
- "github.com/wcharczuk/go-chart/v2"
+ "git.smarteching.com/zeni/go-chart/v2"
)
func BenchmarkMultiChartPNGRender(b *testing.B) {
diff --git a/echarts.go b/echarts.go
index fbe9a36..aaef1f1 100644
--- a/echarts.go
+++ b/echarts.go
@@ -29,7 +29,7 @@ import (
"regexp"
"strconv"
- "github.com/wcharczuk/go-chart/v2"
+ "git.smarteching.com/zeni/go-chart/v2"
)
func convertToArray(data []byte) []byte {
@@ -344,6 +344,11 @@ func (esList EChartsSeriesList) ToSeriesList() SeriesList {
Data: NewSeriesDataFromValues(dataItem.Value.values),
Max: item.Max,
Min: item.Min,
+ Label: SeriesLabel{
+ Color: parseColor(item.Label.Color),
+ Show: item.Label.Show,
+ Distance: item.Label.Distance,
+ },
})
}
continue
diff --git a/echarts_test.go b/echarts_test.go
index 2ce1715..2077278 100644
--- a/echarts_test.go
+++ b/echarts_test.go
@@ -27,7 +27,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
- "github.com/wcharczuk/go-chart/v2/drawing"
+ "git.smarteching.com/zeni/go-chart/v2/drawing"
)
func TestConvertToArray(t *testing.T) {
diff --git a/examples/area_line_chart/main.go b/examples/area_line_chart/main.go
index 7a84df0..57ca1e9 100644
--- a/examples/area_line_chart/main.go
+++ b/examples/area_line_chart/main.go
@@ -1,11 +1,10 @@
package main
import (
- "io/ioutil"
"os"
"path/filepath"
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func writeFile(buf []byte) error {
@@ -16,7 +15,7 @@ func writeFile(buf []byte) error {
}
file := filepath.Join(tmpPath, "area-line-chart.png")
- err = ioutil.WriteFile(file, buf, 0600)
+ err = os.WriteFile(file, buf, 0600)
if err != nil {
return err
}
diff --git a/examples/bar_chart/main.go b/examples/bar_chart/main.go
index c559a76..91c9f81 100644
--- a/examples/bar_chart/main.go
+++ b/examples/bar_chart/main.go
@@ -1,11 +1,10 @@
package main
import (
- "io/ioutil"
"os"
"path/filepath"
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func writeFile(buf []byte) error {
@@ -16,7 +15,7 @@ func writeFile(buf []byte) error {
}
file := filepath.Join(tmpPath, "bar-chart.png")
- err = ioutil.WriteFile(file, buf, 0600)
+ err = os.WriteFile(file, buf, 0600)
if err != nil {
return err
}
diff --git a/examples/charts/main.go b/examples/charts/main.go
index 76aa42c..81bc4f2 100644
--- a/examples/charts/main.go
+++ b/examples/charts/main.go
@@ -6,7 +6,7 @@ import (
"net/http"
"strconv"
- charts "github.com/vicanso/go-charts/v2"
+ charts "git.smarteching.com/zeni/go-charts/v2"
)
var html = `
diff --git a/examples/chinese/main.go b/examples/chinese/main.go
index d77216a..601f54e 100644
--- a/examples/chinese/main.go
+++ b/examples/chinese/main.go
@@ -5,7 +5,7 @@ import (
"os"
"path/filepath"
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func writeFile(buf []byte) error {
@@ -16,7 +16,7 @@ func writeFile(buf []byte) error {
}
file := filepath.Join(tmpPath, "chinese-line-chart.png")
- err = ioutil.WriteFile(file, buf, 0600)
+ err = os.WriteFile(file, buf, 0600)
if err != nil {
return err
}
diff --git a/examples/funnel_chart/main.go b/examples/funnel_chart/main.go
index 24f8afe..653f834 100644
--- a/examples/funnel_chart/main.go
+++ b/examples/funnel_chart/main.go
@@ -1,11 +1,10 @@
package main
import (
- "io/ioutil"
"os"
"path/filepath"
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func writeFile(buf []byte) error {
@@ -16,7 +15,7 @@ func writeFile(buf []byte) error {
}
file := filepath.Join(tmpPath, "funnel-chart.png")
- err = ioutil.WriteFile(file, buf, 0600)
+ err = os.WriteFile(file, buf, 0600)
if err != nil {
return err
}
diff --git a/examples/horizontal_bar_chart/main.go b/examples/horizontal_bar_chart/main.go
index a1c50a7..f5d8497 100644
--- a/examples/horizontal_bar_chart/main.go
+++ b/examples/horizontal_bar_chart/main.go
@@ -1,11 +1,10 @@
package main
import (
- "io/ioutil"
"os"
"path/filepath"
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func writeFile(buf []byte) error {
@@ -16,7 +15,7 @@ func writeFile(buf []byte) error {
}
file := filepath.Join(tmpPath, "horizontal-bar-chart.png")
- err = ioutil.WriteFile(file, buf, 0600)
+ err = os.WriteFile(file, buf, 0600)
if err != nil {
return err
}
@@ -66,6 +65,9 @@ func main() {
"China",
"World",
}),
+ func(opt *charts.ChartOption) {
+ opt.SeriesList[0].RoundRadius = 5
+ },
)
if err != nil {
panic(err)
diff --git a/examples/line_chart/main.go b/examples/line_chart/main.go
index c1478a6..baee8a3 100644
--- a/examples/line_chart/main.go
+++ b/examples/line_chart/main.go
@@ -2,11 +2,10 @@ package main
import (
"fmt"
- "io/ioutil"
"os"
"path/filepath"
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func writeFile(buf []byte) error {
@@ -17,7 +16,7 @@ func writeFile(buf []byte) error {
}
file := filepath.Join(tmpPath, "line-chart.png")
- err = ioutil.WriteFile(file, buf, 0600)
+ err = os.WriteFile(file, buf, 0600)
if err != nil {
return err
}
@@ -97,6 +96,11 @@ func main() {
Top: 5,
Bottom: 10,
}
+ opt.YAxisOptions = []charts.YAxisOption{
+ {
+ SplitLineShow: charts.FalseFlag(),
+ },
+ }
opt.SymbolShow = charts.FalseFlag()
opt.LineStrokeWidth = 1
opt.ValueFormatter = func(f float64) string {
diff --git a/examples/painter/main.go b/examples/painter/main.go
index 3c31ce4..1b842b3 100644
--- a/examples/painter/main.go
+++ b/examples/painter/main.go
@@ -1,12 +1,11 @@
package main
import (
- "io/ioutil"
"os"
"path/filepath"
- charts "github.com/vicanso/go-charts/v2"
- "github.com/wcharczuk/go-chart/v2/drawing"
+ charts "git.smarteching.com/zeni/go-charts/v2"
+ "git.smarteching.com/zeni/go-chart/v2/drawing"
)
func writeFile(buf []byte) error {
@@ -17,7 +16,7 @@ func writeFile(buf []byte) error {
}
file := filepath.Join(tmpPath, "painter.png")
- err = ioutil.WriteFile(file, buf, 0600)
+ err = os.WriteFile(file, buf, 0600)
if err != nil {
return err
}
diff --git a/examples/pie_chart/main.go b/examples/pie_chart/main.go
index 3721ed1..5d70438 100644
--- a/examples/pie_chart/main.go
+++ b/examples/pie_chart/main.go
@@ -1,11 +1,10 @@
package main
import (
- "io/ioutil"
"os"
"path/filepath"
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func writeFile(buf []byte) error {
@@ -16,7 +15,7 @@ func writeFile(buf []byte) error {
}
file := filepath.Join(tmpPath, "pie-chart.png")
- err = ioutil.WriteFile(file, buf, 0600)
+ err = os.WriteFile(file, buf, 0600)
if err != nil {
return err
}
diff --git a/examples/radar_chart/main.go b/examples/radar_chart/main.go
index 51f7409..e7053af 100644
--- a/examples/radar_chart/main.go
+++ b/examples/radar_chart/main.go
@@ -1,11 +1,10 @@
package main
import (
- "io/ioutil"
"os"
"path/filepath"
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func writeFile(buf []byte) error {
@@ -16,7 +15,7 @@ func writeFile(buf []byte) error {
}
file := filepath.Join(tmpPath, "radar-chart.png")
- err = ioutil.WriteFile(file, buf, 0600)
+ err = os.WriteFile(file, buf, 0600)
if err != nil {
return err
}
diff --git a/examples/table/main.go b/examples/table/main.go
index 2701ec1..de994eb 100644
--- a/examples/table/main.go
+++ b/examples/table/main.go
@@ -1,14 +1,13 @@
package main
import (
- "io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"
- "github.com/vicanso/go-charts/v2"
- "github.com/wcharczuk/go-chart/v2/drawing"
+ "git.smarteching.com/zeni/go-charts/v2"
+ "git.smarteching.com/zeni/go-chart/v2/drawing"
)
func writeFile(buf []byte, filename string) error {
@@ -19,7 +18,7 @@ func writeFile(buf []byte, filename string) error {
}
file := filepath.Join(tmpPath, filename)
- err = ioutil.WriteFile(file, buf, 0600)
+ err = os.WriteFile(file, buf, 0600)
if err != nil {
return err
}
diff --git a/examples/time_line_chart/main.go b/examples/time_line_chart/main.go
index 10932cd..c6c93bf 100644
--- a/examples/time_line_chart/main.go
+++ b/examples/time_line_chart/main.go
@@ -3,13 +3,12 @@ package main
import (
"crypto/rand"
"fmt"
- "io/ioutil"
"math/big"
"os"
"path/filepath"
"time"
- "github.com/vicanso/go-charts/v2"
+ "git.smarteching.com/zeni/go-charts/v2"
)
func writeFile(buf []byte) error {
@@ -20,7 +19,7 @@ func writeFile(buf []byte) error {
}
file := filepath.Join(tmpPath, "time-line-chart.png")
- err = ioutil.WriteFile(file, buf, 0600)
+ err = os.WriteFile(file, buf, 0600)
if err != nil {
return err
}
diff --git a/font.go b/font.go
index dae5141..828654e 100644
--- a/font.go
+++ b/font.go
@@ -27,7 +27,7 @@ import (
"sync"
"github.com/golang/freetype/truetype"
- "github.com/wcharczuk/go-chart/v2/roboto"
+ "git.smarteching.com/zeni/go-chart/v2/roboto"
)
var fonts = sync.Map{}
diff --git a/font_test.go b/font_test.go
index 9dc731c..e0c56b2 100644
--- a/font_test.go
+++ b/font_test.go
@@ -26,7 +26,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
- "github.com/wcharczuk/go-chart/v2/roboto"
+ "git.smarteching.com/zeni/go-chart/v2/roboto"
)
func TestInstallFont(t *testing.T) {
diff --git a/go.mod b/go.mod
index d8a492c..76a47b6 100644
--- a/go.mod
+++ b/go.mod
@@ -1,17 +1,17 @@
-module github.com/vicanso/go-charts/v2
+module git.smarteching.com/zeni/go-charts/v2
-go 1.17
+go 1.24.1
require (
+ git.smarteching.com/zeni/go-chart/v2 v2.1.4
github.com/dustin/go-humanize v1.0.1
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
- github.com/stretchr/testify v1.8.2
- github.com/wcharczuk/go-chart/v2 v2.1.0
+ github.com/stretchr/testify v1.10.0
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
- golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 // indirect
+ golang.org/x/image v0.21.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
diff --git a/go.sum b/go.sum
index ac1d9f7..3e1a48a 100644
--- a/go.sum
+++ b/go.sum
@@ -1,4 +1,5 @@
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+git.smarteching.com/zeni/go-chart/v2 v2.1.4 h1:pF06+F6eqJLIG8uMiTVPR5TygPGMjM/FHMzTxmu5V/Q=
+git.smarteching.com/zeni/go-chart/v2 v2.1.4/go.mod h1:b3ueW9h3pGGXyhkormZAvilHaG4+mQti+bMNPdQBeOQ=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
@@ -7,20 +8,11 @@ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF0
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
-github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
-github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/wcharczuk/go-chart/v2 v2.1.0 h1:tY2slqVQ6bN+yHSnDYwZebLQFkphK4WNrVwnt7CJZ2I=
-github.com/wcharczuk/go-chart/v2 v2.1.0/go.mod h1:yx7MvAVNcP/kN9lKXM/NTce4au4DFN99j6i1OwDclNA=
-golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 h1:QelT11PB4FXiDEXucrfNckHoFxwt8USGY1ajP1ZF5lM=
-golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s=
+golang.org/x/image v0.21.0/go.mod h1:vUbsLavqK/W303ZroQQVKQ+Af3Yl6Uz1Ppu5J/cLz78=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/grid_test.go b/grid_test.go
index 3110a2b..fa9c3a6 100644
--- a/grid_test.go
+++ b/grid_test.go
@@ -26,7 +26,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
- "github.com/wcharczuk/go-chart/v2/drawing"
+ "git.smarteching.com/zeni/go-chart/v2/drawing"
)
func TestGrid(t *testing.T) {
diff --git a/horizontal_bar_chart.go b/horizontal_bar_chart.go
index 2ab4c03..ed091c9 100644
--- a/horizontal_bar_chart.go
+++ b/horizontal_bar_chart.go
@@ -24,7 +24,7 @@ package charts
import (
"github.com/golang/freetype/truetype"
- "github.com/wcharczuk/go-chart/v2"
+ "git.smarteching.com/zeni/go-chart/v2"
)
type horizontalBarChart struct {
@@ -50,6 +50,8 @@ type HorizontalBarChartOption struct {
// The legend option
Legend LegendOption
BarHeight int
+ // Margin of bar
+ BarMargin int
}
// NewHorizontalBarChart returns a horizontal bar chart renderer
@@ -81,6 +83,9 @@ func (h *horizontalBarChart) render(result *defaultRenderResult, seriesList Seri
margin = 5
barMargin = 3
}
+ if opt.BarMargin > 0 {
+ barMargin = opt.BarMargin
+ }
seriesCount := len(seriesList)
// 总的高度-两个margin-(总数-1)的barMargin
barHeight := (height - 2*margin - barMargin*(seriesCount-1)) / seriesCount
@@ -136,14 +141,26 @@ func (h *horizontalBarChart) render(result *defaultRenderResult, seriesList Seri
fillColor = item.Style.FillColor
}
right := w
- seriesPainter.OverrideDrawingStyle(Style{
- FillColor: fillColor,
- }).Rect(chart.Box{
- Top: y,
- Left: 0,
- Right: right,
- Bottom: y + barHeight,
- })
+ if series.RoundRadius <= 0 {
+ seriesPainter.OverrideDrawingStyle(Style{
+ FillColor: fillColor,
+ }).Rect(chart.Box{
+ Top: y,
+ Left: 0,
+ Right: right,
+ Bottom: y + barHeight,
+ })
+ } else {
+ seriesPainter.OverrideDrawingStyle(Style{
+ FillColor: fillColor,
+ }).RoundedRect(chart.Box{
+ Top: y,
+ Left: 0,
+ Right: right,
+ Bottom: y + barHeight,
+ }, series.RoundRadius)
+ }
+
// 如果label不需要展示,则返回
if labelPainter == nil {
continue
diff --git a/line_chart.go b/line_chart.go
index bdbd38e..fb1d16a 100644
--- a/line_chart.go
+++ b/line_chart.go
@@ -26,7 +26,7 @@ import (
"math"
"github.com/golang/freetype/truetype"
- "github.com/wcharczuk/go-chart/v2/drawing"
+ "git.smarteching.com/zeni/go-chart/v2/drawing"
)
type lineChart struct {
@@ -115,6 +115,9 @@ func (l *lineChart) render(result *defaultRenderResult, seriesList SeriesList) (
StrokeColor: seriesColor,
StrokeWidth: strokeWidth,
}
+ if len(series.Style.StrokeDashArray) > 0 {
+ drawingStyle.StrokeDashArray = series.Style.StrokeDashArray
+ }
yRange := result.axisRanges[series.AxisIndex]
points := make([]Point, 0)
diff --git a/mark_line_test.go b/mark_line_test.go
index 00d19ef..0448cda 100644
--- a/mark_line_test.go
+++ b/mark_line_test.go
@@ -26,7 +26,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
- "github.com/wcharczuk/go-chart/v2/drawing"
+ "git.smarteching.com/zeni/go-chart/v2/drawing"
)
func TestMarkLine(t *testing.T) {
diff --git a/mark_point_test.go b/mark_point_test.go
index ffa01a7..298345b 100644
--- a/mark_point_test.go
+++ b/mark_point_test.go
@@ -26,7 +26,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
- "github.com/wcharczuk/go-chart/v2/drawing"
+ "git.smarteching.com/zeni/go-chart/v2/drawing"
)
func TestMarkPoint(t *testing.T) {
diff --git a/painter.go b/painter.go
index 18496fd..bee646f 100644
--- a/painter.go
+++ b/painter.go
@@ -28,7 +28,7 @@ import (
"math"
"github.com/golang/freetype/truetype"
- "github.com/wcharczuk/go-chart/v2"
+ "git.smarteching.com/zeni/go-chart/v2"
)
type ValueFormatter func(float64) string
@@ -803,6 +803,48 @@ func (p *Painter) Rect(box Box) *Painter {
return p
}
+func (p *Painter) RoundedRect(box Box, radius int) *Painter {
+ r := (box.Right - box.Left) / 2
+ if radius > r {
+ radius = r
+ }
+ rx := float64(radius)
+ ry := float64(radius)
+ p.MoveTo(box.Left+radius, box.Top)
+ p.LineTo(box.Right-radius, box.Top)
+
+ cx := box.Right - radius
+ cy := box.Top + radius
+ // right top
+ p.ArcTo(cx, cy, rx, ry, -math.Pi/2, math.Pi/2)
+
+ p.LineTo(box.Right, box.Bottom-radius)
+
+ // right bottom
+ cx = box.Right - radius
+ cy = box.Bottom - radius
+ p.ArcTo(cx, cy, rx, ry, 0.0, math.Pi/2)
+
+ p.LineTo(box.Left+radius, box.Bottom)
+
+ // left bottom
+ cx = box.Left + radius
+ cy = box.Bottom - radius
+ p.ArcTo(cx, cy, rx, ry, math.Pi/2, math.Pi/2)
+
+ p.LineTo(box.Left, box.Top+radius)
+
+ // left top
+ cx = box.Left + radius
+ cy = box.Top + radius
+ p.ArcTo(cx, cy, rx, ry, math.Pi, math.Pi/2)
+
+ p.Close()
+ p.FillStroke()
+ p.Fill()
+ return p
+}
+
func (p *Painter) LegendLineDot(box Box) *Painter {
width := box.Width()
height := box.Height()
@@ -818,3 +860,7 @@ func (p *Painter) LegendLineDot(box Box) *Painter {
p.FillStroke()
return p
}
+
+func (p *Painter) GetRenderer() chart.Renderer {
+ return p.render
+}
diff --git a/painter_test.go b/painter_test.go
index 2392d5b..07c4113 100644
--- a/painter_test.go
+++ b/painter_test.go
@@ -28,8 +28,8 @@ import (
"github.com/golang/freetype/truetype"
"github.com/stretchr/testify/assert"
- "github.com/wcharczuk/go-chart/v2"
- "github.com/wcharczuk/go-chart/v2/drawing"
+ "git.smarteching.com/zeni/go-chart/v2"
+ "git.smarteching.com/zeni/go-chart/v2/drawing"
)
func TestPainterOption(t *testing.T) {
@@ -343,6 +343,29 @@ func TestPainter(t *testing.T) {
}
}
+func TestRoundedRect(t *testing.T) {
+ assert := assert.New(t)
+ p, err := NewPainter(PainterOptions{
+ Width: 400,
+ Height: 300,
+ Type: ChartOutputSVG,
+ })
+ assert.Nil(err)
+ p.OverrideDrawingStyle(Style{
+ FillColor: drawing.ColorWhite,
+ StrokeWidth: 1,
+ StrokeColor: drawing.ColorWhite,
+ }).RoundedRect(Box{
+ Left: 10,
+ Right: 30,
+ Bottom: 150,
+ Top: 10,
+ }, 5)
+ buf, err := p.Bytes()
+ assert.Nil(err)
+ assert.Equal("", string(buf))
+}
+
func TestPainterTextFit(t *testing.T) {
assert := assert.New(t)
p, err := NewPainter(PainterOptions{
diff --git a/pie_chart.go b/pie_chart.go
index b4714ac..5c04ed8 100644
--- a/pie_chart.go
+++ b/pie_chart.go
@@ -27,7 +27,7 @@ import (
"math"
"github.com/golang/freetype/truetype"
- "github.com/wcharczuk/go-chart/v2"
+ "git.smarteching.com/zeni/go-chart/v2"
)
type pieChart struct {
@@ -63,6 +63,96 @@ func NewPieChart(p *Painter, opt PieChartOption) *pieChart {
}
}
+type sector struct {
+ value float64
+ percent float64
+ cx int
+ cy int
+ rx float64
+ ry float64
+ start float64
+ delta float64
+ offset int
+ quadrant int
+ lineStartX int
+ lineStartY int
+ lineBranchX int
+ lineBranchY int
+ lineEndX int
+ lineEndY int
+ showLabel bool
+ label string
+ series Series
+ color Color
+}
+
+func NewSector(cx int, cy int, radius float64, labelRadius float64, value float64, currentValue float64, totalValue float64, labelLineLength int, label string, series Series, color Color) sector {
+ s := sector{}
+ s.value = value
+ s.percent = value / totalValue
+ s.cx = cx
+ s.cy = cy
+ s.rx = radius
+ s.ry = radius
+ p := (currentValue + value/2) / totalValue
+ if p < 0.25 {
+ s.quadrant = 1
+ } else if p < 0.5 {
+ s.quadrant = 4
+ } else if p < 0.75 {
+ s.quadrant = 3
+ } else {
+ s.quadrant = 2
+ }
+ s.start = chart.PercentToRadians(currentValue/totalValue) - math.Pi/2
+ s.delta = chart.PercentToRadians(value / totalValue)
+ angle := s.start + s.delta/2
+ s.lineStartX = cx + int(radius*math.Cos(angle))
+ s.lineStartY = cy + int(radius*math.Sin(angle))
+ s.lineBranchX = cx + int(labelRadius*math.Cos(angle))
+ s.lineBranchY = cy + int(labelRadius*math.Sin(angle))
+ s.offset = labelLineLength
+ if s.lineBranchX <= cx {
+ s.offset *= -1
+ }
+ s.lineEndX = s.lineBranchX + s.offset
+ s.lineEndY = s.lineBranchY
+ s.series = series
+ s.color = color
+ s.showLabel = series.Label.Show
+ s.label = NewPieLabelFormatter([]string{label}, series.Label.Formatter)(0, s.value, s.percent)
+ return s
+}
+
+func (s *sector) calculateY(prevY int) int {
+ for i := 0; i <= s.cy; i++ {
+ if s.quadrant <= 2 {
+ if (prevY - s.lineBranchY) > labelFontSize+5 {
+ break
+ }
+ s.lineBranchY -= 1
+ } else {
+ if (s.lineBranchY - prevY) > labelFontSize+5 {
+ break
+ }
+ s.lineBranchY += 1
+ }
+ }
+ s.lineEndY = s.lineBranchY
+ return s.lineBranchY
+}
+
+func (s *sector) calculateTextXY(textBox Box) (x int, y int) {
+ textMargin := 3
+ x = s.lineEndX + textMargin
+ y = s.lineEndY + textBox.Height()>>1 - 1
+ if s.offset < 0 {
+ textWidth := textBox.Width()
+ x = s.lineEndX - textWidth - textMargin
+ }
+ return
+}
+
func (p *pieChart) render(result *defaultRenderResult, seriesList SeriesList) (Box, error) {
opt := p.opt
values := make([]float64, len(seriesList))
@@ -101,98 +191,103 @@ func (p *pieChart) render(result *defaultRenderResult, seriesList SeriesList) (B
theme := opt.Theme
currentValue := float64(0)
- prevPoints := make([]Point, 0)
- isOverride := func(x, y int) bool {
- for _, p := range prevPoints {
- if math.Abs(float64(p.Y-y)) > labelFontSize {
- continue
- }
- // label可能较多内容,不好计算横向占用空间
- // 因此x的位置需要中间位置两侧,否则认为override
- if (p.X <= cx && x <= cx) ||
- (p.X > cx && x > cx) {
- return true
+ var quadrant1, quadrant2, quadrant3, quadrant4 []sector
+ for index, v := range values {
+ series := seriesList[index]
+ color := theme.GetSeriesColor(index)
+ if index == len(values)-1 {
+ if color == theme.GetSeriesColor(0) {
+ color = theme.GetSeriesColor(1)
}
}
- return false
+ s := NewSector(cx, cy, radius, labelRadius, v, currentValue, total, labelLineWidth, seriesNames[index], series, color)
+ switch quadrant := s.quadrant; quadrant {
+ case 1:
+ quadrant1 = append([]sector{s}, quadrant1...)
+ case 2:
+ quadrant2 = append(quadrant2, s)
+ case 3:
+ quadrant3 = append([]sector{s}, quadrant3...)
+ case 4:
+ quadrant4 = append(quadrant4, s)
+ }
+ currentValue += v
}
+ sectors := append(quadrant1, quadrant4...)
+ sectors = append(sectors, quadrant3...)
+ sectors = append(sectors, quadrant2...)
- for index, v := range values {
+ currentQuadrant := 0
+ prevY := 0
+ maxY := 0
+ minY := 0
+ for _, s := range sectors {
seriesPainter.OverrideDrawingStyle(Style{
StrokeWidth: 1,
- StrokeColor: theme.GetSeriesColor(index),
- FillColor: theme.GetSeriesColor(index),
+ StrokeColor: s.color,
+ FillColor: s.color,
})
- seriesPainter.MoveTo(cx, cy)
- start := chart.PercentToRadians(currentValue/total) - math.Pi/2
- currentValue += v
- percent := (v / total)
- delta := chart.PercentToRadians(percent)
- seriesPainter.ArcTo(cx, cy, radius, radius, start, delta).
- LineTo(cx, cy).
- Close().
- FillStroke()
-
- series := seriesList[index]
- // 是否显示label
- showLabel := series.Label.Show
- if !showLabel {
+ seriesPainter.MoveTo(s.cx, s.cy)
+ seriesPainter.ArcTo(s.cx, s.cy, s.rx, s.ry, s.start, s.delta).LineTo(s.cx, s.cy).Close().FillStroke()
+ if !s.showLabel {
continue
}
-
- // label的角度为饼块中间
- angle := start + delta/2
- startx := cx + int(radius*math.Cos(angle))
- starty := cy + int(radius*math.Sin(angle))
-
- endx := cx + int(labelRadius*math.Cos(angle))
- endy := cy + int(labelRadius*math.Sin(angle))
- // 计算是否有重叠,如果有则调整y坐标位置
- // 最多只尝试5次
- for i := 0; i < 5; i++ {
- if !isOverride(endx, endy) {
- break
+ if currentQuadrant != s.quadrant {
+ if s.quadrant == 1 {
+ minY = cy * 2
+ maxY = 0
+ prevY = cy * 2
}
- endy -= (labelFontSize << 1)
+ if s.quadrant == 2 {
+ if currentQuadrant != 3 {
+ prevY = s.lineEndY
+ } else {
+ prevY = minY
+ }
+ }
+ if s.quadrant == 3 {
+ if currentQuadrant != 4 {
+ prevY = s.lineEndY
+ } else {
+ minY = cy * 2
+ maxY = 0
+ prevY = 0
+ }
+ }
+ if s.quadrant == 4 {
+ if currentQuadrant != 1 {
+ prevY = s.lineEndY
+ } else {
+ prevY = maxY
+ }
+ }
+ currentQuadrant = s.quadrant
}
- prevPoints = append(prevPoints, Point{
- X: endx,
- Y: endy,
- })
-
- seriesPainter.MoveTo(startx, starty)
- seriesPainter.LineTo(endx, endy)
- offset := labelLineWidth
- if endx < cx {
- offset *= -1
+ prevY = s.calculateY(prevY)
+ if prevY > maxY {
+ maxY = prevY
}
- seriesPainter.MoveTo(endx, endy)
- endx += offset
- seriesPainter.LineTo(endx, endy)
+ if prevY < minY {
+ minY = prevY
+ }
+ seriesPainter.MoveTo(s.lineStartX, s.lineStartY)
+ seriesPainter.LineTo(s.lineBranchX, s.lineBranchY)
+ seriesPainter.MoveTo(s.lineBranchX, s.lineBranchY)
+ seriesPainter.LineTo(s.lineEndX, s.lineEndY)
seriesPainter.Stroke()
-
textStyle := Style{
FontColor: theme.GetTextColor(),
FontSize: labelFontSize,
Font: opt.Font,
}
- if !series.Label.Color.IsZero() {
- textStyle.FontColor = series.Label.Color
+ if !s.series.Label.Color.IsZero() {
+ textStyle.FontColor = s.series.Label.Color
}
seriesPainter.OverrideTextStyle(textStyle)
- text := NewPieLabelFormatter(seriesNames, series.Label.Formatter)(index, v, percent)
- textBox := seriesPainter.MeasureText(text)
- textMargin := 3
- x := endx + textMargin
- y := endy + textBox.Height()>>1 - 1
- if offset < 0 {
- textWidth := textBox.Width()
- x = endx - textWidth - textMargin
- }
- seriesPainter.Text(text, x, y)
+ x, y := s.calculateTextXY(seriesPainter.MeasureText(s.label))
+ seriesPainter.Text(s.label, x, y)
}
-
return p.p.box, nil
}
diff --git a/pie_chart_test.go b/pie_chart_test.go
index c373a7e..3795d32 100644
--- a/pie_chart_test.go
+++ b/pie_chart_test.go
@@ -23,6 +23,7 @@
package charts
import (
+ "strconv"
"testing"
"github.com/stretchr/testify/assert"
@@ -98,3 +99,435 @@ func TestPieChart(t *testing.T) {
assert.Equal(tt.result, string(data))
}
}
+
+func TestPieChartWithLabelsValuesSortedDescending(t *testing.T) {
+ assert := assert.New(t)
+
+ tests := []struct {
+ render func(*Painter) ([]byte, error)
+ result string
+ }{
+ {
+ render: func(p *Painter) ([]byte, error) {
+ values := []float64{
+ 84358845,
+ 68070697,
+ 58850717,
+ 48059777,
+ 36753736,
+ 19051562,
+ 17947406,
+ 11754004,
+ 10827529,
+ 10521556,
+ 10467366,
+ 10394055,
+ 9597085,
+ 9104772,
+ 6447710,
+ 5932654,
+ 5563970,
+ 5428792,
+ 5194336,
+ 3850894,
+ 2857279,
+ 2116792,
+ 1883008,
+ 1373101,
+ 920701,
+ 660809,
+ 542051,
+ }
+ _, err := NewPieChart(p, PieChartOption{
+ SeriesList: NewPieSeriesList(values, PieSeriesOption{
+ Label: SeriesLabel{
+ Show: true,
+ Formatter: "{b} ({c} ≅ {d})",
+ },
+ Radius: "200",
+ }),
+ Title: TitleOption{
+ Text: "European Union member states by population",
+ Left: PositionRight,
+ },
+ Padding: Box{
+ Top: 20,
+ Right: 20,
+ Bottom: 20,
+ Left: 20,
+ },
+ Legend: LegendOption{
+ Data: []string{
+ "Germany",
+ "France",
+ "Italy",
+ "Spain",
+ "Poland",
+ "Romania",
+ "Netherlands",
+ "Belgium",
+ "Czech Republic",
+ "Sweden",
+ "Portugal",
+ "Greece",
+ "Hungary",
+ "Austria",
+ "Bulgaria",
+ "Denmark",
+ "Finland",
+ "Slovakia",
+ "Ireland",
+ "Croatia",
+ "Lithuania",
+ "Slovenia",
+ "Latvia",
+ "Estonia",
+ "Cyprus",
+ "Luxembourg",
+ "Malta",
+ },
+ Show: FalseFlag(),
+ },
+ }).Render()
+ if err != nil {
+ return nil, err
+ }
+ return p.Bytes()
+ },
+ result: "",
+ },
+ }
+ for _, tt := range tests {
+ p, err := NewPainter(PainterOptions{
+ Type: ChartOutputSVG,
+ Width: 1000,
+ Height: 800,
+ }, PainterThemeOption(defaultTheme))
+ assert.Nil(err)
+ data, err := tt.render(p.Child(PainterPaddingOption(Box{
+ Left: 20,
+ Top: 20,
+ Right: 20,
+ Bottom: 20,
+ })))
+ assert.Nil(err)
+ assert.Equal(tt.result, string(data))
+ }
+}
+
+func TestPieChartWithLabelsValuesUnsorted(t *testing.T) {
+ assert := assert.New(t)
+
+ tests := []struct {
+ render func(*Painter) ([]byte, error)
+ result string
+ }{
+ {
+ render: func(p *Painter) ([]byte, error) {
+ values := []float64{
+ 9104772,
+ 11754004,
+ 6447710,
+ 3850894,
+ 920701,
+ 10827529,
+ 5932654,
+ 1373101,
+ 5563970,
+ 68070697,
+ 84358845,
+ 10394055,
+ 9597085,
+ 5194336,
+ 58850717,
+ 1883008,
+ 2857279,
+ 660809,
+ 542051,
+ 17947406,
+ 36753736,
+ 10467366,
+ 19051562,
+ 5428792,
+ 2116792,
+ 48059777,
+ 10521556,
+ }
+ _, err := NewPieChart(p, PieChartOption{
+ SeriesList: NewPieSeriesList(values, PieSeriesOption{
+ Label: SeriesLabel{
+ Show: true,
+ Formatter: "{b} ({c} ≅ {d})",
+ },
+ Radius: "200",
+ }),
+ Title: TitleOption{
+ Text: "European Union member states by population",
+ Left: PositionRight,
+ },
+ Padding: Box{
+ Top: 20,
+ Right: 20,
+ Bottom: 20,
+ Left: 20,
+ },
+ Legend: LegendOption{
+ Data: []string{
+ "Austria",
+ "Belgium",
+ "Bulgaria",
+ "Croatia",
+ "Cyprus",
+ "Czech Republic",
+ "Denmark",
+ "Estonia",
+ "Finland",
+ "France",
+ "Germany",
+ "Greece",
+ "Hungary",
+ "Ireland",
+ "Italy",
+ "Latvia",
+ "Lithuania",
+ "Luxembourg",
+ "Malta",
+ "Netherlands",
+ "Poland",
+ "Portugal",
+ "Romania",
+ "Slovakia",
+ "Slovenia",
+ "Spain",
+ "Sweden",
+ },
+ Show: FalseFlag(),
+ },
+ }).Render()
+ if err != nil {
+ return nil, err
+ }
+ return p.Bytes()
+ },
+ result: "",
+ },
+ }
+ for _, tt := range tests {
+ p, err := NewPainter(PainterOptions{
+ Type: ChartOutputSVG,
+ Width: 1000,
+ Height: 800,
+ }, PainterThemeOption(defaultTheme))
+ assert.Nil(err)
+ data, err := tt.render(p.Child(PainterPaddingOption(Box{
+ Left: 20,
+ Top: 20,
+ Right: 20,
+ Bottom: 20,
+ })))
+ assert.Nil(err)
+ assert.Equal(tt.result, string(data))
+ }
+}
+
+func TestPieChartWith100Labels(t *testing.T) {
+ assert := assert.New(t)
+
+ tests := []struct {
+ render func(*Painter) ([]byte, error)
+ result string
+ }{
+ {
+ render: func(p *Painter) ([]byte, error) {
+ var values []float64
+ var labels []string
+ for i := 1; i <= 100; i++ {
+ values = append(values, float64(1))
+ labels = append(labels, "Label "+strconv.Itoa(i))
+ }
+ _, err := NewPieChart(p, PieChartOption{
+ SeriesList: NewPieSeriesList(values, PieSeriesOption{
+ Label: SeriesLabel{
+ Show: true,
+ },
+ Radius: "200",
+ }),
+ Title: TitleOption{
+ Text: "Test with 100 labels",
+ Left: PositionRight,
+ },
+ Padding: Box{
+ Top: 20,
+ Right: 20,
+ Bottom: 20,
+ Left: 20,
+ },
+ Legend: LegendOption{
+ Data: labels,
+ Show: FalseFlag(),
+ },
+ }).Render()
+ if err != nil {
+ return nil, err
+ }
+ return p.Bytes()
+ },
+ result: "",
+ },
+ }
+ for _, tt := range tests {
+ p, err := NewPainter(PainterOptions{
+ Type: ChartOutputSVG,
+ Width: 1000,
+ Height: 900,
+ }, PainterThemeOption(defaultTheme))
+ assert.Nil(err)
+ data, err := tt.render(p.Child(PainterPaddingOption(Box{
+ Left: 20,
+ Top: 20,
+ Right: 20,
+ Bottom: 20,
+ })))
+ assert.Nil(err)
+ assert.Equal(tt.result, string(data))
+ }
+}
+
+func TestPieChartFixLabelPos72586(t *testing.T) {
+ assert := assert.New(t)
+
+ tests := []struct {
+ render func(*Painter) ([]byte, error)
+ result string
+ }{
+ {
+ render: func(p *Painter) ([]byte, error) {
+ values := []float64{
+ 397594,
+ 185596,
+ 149086,
+ 144258,
+ 120194,
+ 117514,
+ 99412,
+ 91135,
+ 87282,
+ 76790,
+ 72586,
+ 58818,
+ 58270,
+ 56306,
+ 55486,
+ 54792,
+ 53746,
+ 51460,
+ 41242,
+ 39476,
+ 37414,
+ 36644,
+ 33784,
+ 32788,
+ 32566,
+ 29608,
+ 29558,
+ 29384,
+ 28166,
+ 26998,
+ 26948,
+ 26054,
+ 25804,
+ 25730,
+ 24438,
+ 23782,
+ 22896,
+ 21404,
+ 428978,
+ }
+ _, err := NewPieChart(p, PieChartOption{
+ SeriesList: NewPieSeriesList(values, PieSeriesOption{
+ Label: SeriesLabel{
+ Show: true,
+ Formatter: "{b} ({c} ≅ {d})",
+ },
+ Radius: "150",
+ }),
+ Title: TitleOption{
+ Text: "Fix label K (72586)",
+ Left: PositionRight,
+ },
+ Padding: Box{
+ Top: 20,
+ Right: 20,
+ Bottom: 20,
+ Left: 20,
+ },
+ Legend: LegendOption{
+ Data: []string{
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H",
+ "I",
+ "J",
+ "K",
+ "L",
+ "M",
+ "N",
+ "O",
+ "P",
+ "Q",
+ "R",
+ "S",
+ "T",
+ "U",
+ "V",
+ "W",
+ "X",
+ "Y",
+ "Z",
+ "AA",
+ "AB",
+ "AC",
+ "AD",
+ "AE",
+ "AF",
+ "AG",
+ "AH",
+ "AI",
+ "AJ",
+ "AK",
+ "AL",
+ "AM",
+ },
+ Show: FalseFlag(),
+ },
+ }).Render()
+ if err != nil {
+ return nil, err
+ }
+ return p.Bytes()
+ },
+ result: "",
+ },
+ }
+ for _, tt := range tests {
+ p, err := NewPainter(PainterOptions{
+ Type: ChartOutputSVG,
+ Width: 1150,
+ Height: 550,
+ }, PainterThemeOption(defaultTheme))
+ assert.Nil(err)
+ data, err := tt.render(p.Child(PainterPaddingOption(Box{
+ Left: 20,
+ Top: 20,
+ Right: 20,
+ Bottom: 20,
+ })))
+ assert.Nil(err)
+ assert.Equal(tt.result, string(data))
+ }
+}
diff --git a/radar_chart.go b/radar_chart.go
index 429850d..cf18135 100644
--- a/radar_chart.go
+++ b/radar_chart.go
@@ -25,9 +25,10 @@ package charts
import (
"errors"
+ "github.com/dustin/go-humanize"
"github.com/golang/freetype/truetype"
- "github.com/wcharczuk/go-chart/v2"
- "github.com/wcharczuk/go-chart/v2/drawing"
+ "git.smarteching.com/zeni/go-chart/v2"
+ "git.smarteching.com/zeni/go-chart/v2/drawing"
)
type radarChart struct {
@@ -230,9 +231,15 @@ func (r *radarChart) render(result *defaultRenderResult, seriesList SeriesList)
StrokeColor: color,
FillColor: dotFillColor,
})
- for _, point := range linePoints {
+ for index, point := range linePoints {
seriesPainter.Circle(dotWith, point.X, point.Y)
seriesPainter.FillStroke()
+ if series.Label.Show && index < len(series.Data) {
+ value := humanize.FtoaWithDigits(series.Data[index].Value, 2)
+ b := seriesPainter.MeasureText(value)
+ seriesPainter.Text(value, point.X-b.Width()/2, point.Y)
+ }
+
}
}
diff --git a/series.go b/series.go
index f28bfa9..da50e64 100644
--- a/series.go
+++ b/series.go
@@ -26,7 +26,7 @@ import (
"strings"
"github.com/dustin/go-humanize"
- "github.com/wcharczuk/go-chart/v2"
+ "git.smarteching.com/zeni/go-chart/v2"
)
type SeriesData struct {
@@ -126,6 +126,8 @@ type Series struct {
Name string
// Radius for Pie chart, e.g.: 40%, default is "40%"
Radius string
+ // Round for bar chart
+ RoundRadius int
// Mark point for series
MarkPoint SeriesMarkPoint
// Make line for series
diff --git a/series_label.go b/series_label.go
index 10fd148..af873fc 100644
--- a/series_label.go
+++ b/series_label.go
@@ -24,7 +24,7 @@ package charts
import (
"github.com/golang/freetype/truetype"
- "github.com/wcharczuk/go-chart/v2"
+ "git.smarteching.com/zeni/go-chart/v2"
)
type labelRenderValue struct {
diff --git a/table.go b/table.go
index 86ef569..3e6f273 100644
--- a/table.go
+++ b/table.go
@@ -26,8 +26,8 @@ import (
"errors"
"github.com/golang/freetype/truetype"
- "github.com/wcharczuk/go-chart/v2"
- "github.com/wcharczuk/go-chart/v2/drawing"
+ "git.smarteching.com/zeni/go-chart/v2"
+ "git.smarteching.com/zeni/go-chart/v2/drawing"
)
type tableChart struct {
diff --git a/theme.go b/theme.go
index a6d624f..85016a5 100644
--- a/theme.go
+++ b/theme.go
@@ -24,7 +24,7 @@ package charts
import (
"github.com/golang/freetype/truetype"
- "github.com/wcharczuk/go-chart/v2/drawing"
+ "git.smarteching.com/zeni/go-chart/v2/drawing"
)
const ThemeDark = "dark"
diff --git a/util.go b/util.go
index b333e6d..87ff31c 100644
--- a/util.go
+++ b/util.go
@@ -29,8 +29,8 @@ import (
"strings"
"github.com/dustin/go-humanize"
- "github.com/wcharczuk/go-chart/v2"
- "github.com/wcharczuk/go-chart/v2/drawing"
+ "git.smarteching.com/zeni/go-chart/v2"
+ "git.smarteching.com/zeni/go-chart/v2/drawing"
)
func TrueFlag() *bool {
diff --git a/util_test.go b/util_test.go
index 62fd08d..5770776 100644
--- a/util_test.go
+++ b/util_test.go
@@ -26,8 +26,8 @@ import (
"testing"
"github.com/stretchr/testify/assert"
- "github.com/wcharczuk/go-chart/v2"
- "github.com/wcharczuk/go-chart/v2/drawing"
+ "git.smarteching.com/zeni/go-chart/v2"
+ "git.smarteching.com/zeni/go-chart/v2/drawing"
)
func TestGetDefaultInt(t *testing.T) {
diff --git a/yaxis.go b/yaxis.go
index bece2cc..e58b7a6 100644
--- a/yaxis.go
+++ b/yaxis.go
@@ -50,6 +50,8 @@ type YAxisOption struct {
DivideCount int
Unit int
isCategoryAxis bool
+ // The flag for show axis split line, set this to true will show axis split line
+ SplitLineShow *bool
}
// NewYAxisOptions returns a y axis option
@@ -100,6 +102,9 @@ func (opt *YAxisOption) ToAxisOption(p *Painter) AxisOption {
axisOpt.StrokeWidth = 1
axisOpt.SplitLineShow = false
}
+ if opt.SplitLineShow != nil {
+ axisOpt.SplitLineShow = *opt.SplitLineShow
+ }
return axisOpt
}