Compare commits

...

21 commits
v2.6.1 ... main

Author SHA1 Message Date
958172a1f1 update URL in examples
Some checks failed
Test / Build (push) Has been cancelled
2025-05-13 21:53:31 -05:00
0eacc8e394 start migration to our packages
Some checks are pending
Test / Build (push) Waiting to run
2025-05-13 21:46:02 -05:00
vicanso
d25a827706 fix: fix label position of pie, #86 2024-08-15 20:37:07 +08:00
vicanso
5842c71b1d refactor: remove unused code 2024-08-01 21:44:52 +08:00
vicanso
e7dc4189d5 feat: support bar margin 2024-06-07 20:35:03 +08:00
vicanso
32e6dd52d0 refactor: export GetRenderer function to get chart renderer 2024-06-05 21:13:03 +08:00
vicanso
9614835723 feat: support rounded rect for horizontal bar chart 2024-05-21 20:26:40 +08:00
vicanso
9b7634c2c2 feat: support rounded rect for bar chart 2024-05-16 20:02:24 +08:00
Tree Xie
5a69c3e5a3
Merge pull request #72 from euerla/main
fix: Label position of the pie chart
2024-03-23 10:33:19 +08:00
Alexander Heidrich
8c6c4e007c fix: Label position of the pie chart 2024-03-22 08:27:06 +01:00
Tree Xie
765febd03a
Merge pull request #71 from euerla/main
fix: Label position of the pie chart
2024-03-09 08:13:02 +08:00
Alexander Heidrich
19a4d783fd fix: Label position of the pie chart 2024-03-08 20:24:13 +01:00
vicanso
06fe1006d5 chore: update test go version 2024-02-11 12:39:39 +08:00
vicanso
f1a231ff4b feat: support split line show option for charts, #69 2024-02-11 12:36:26 +08:00
Tree Xie
c7c0655113
Merge pull request #67 from ssexuejinwei/main
support dash line for line chart
2024-01-02 19:35:16 +08:00
xuejinwei.1112
310800a5f0 support dash line for line chart 2024-01-02 12:32:56 +08:00
vicanso
e09ab2c3c7 Revert "chore: update modules"
This reverts commit c2f709a742.
2023-12-27 20:37:18 +08:00
vicanso
c2f709a742 chore: update modules 2023-12-27 20:34:05 +08:00
vicanso
98af9866a4 refactor: support label show for radar chart, #62 2023-12-27 20:33:12 +08:00
Tree Xie
c302d0ffa4
Merge pull request #65 from vicanso/revert-56-xAxisImprovements
Revert "Improvements to how the X Axis is rendered"
2023-12-27 18:21:05 +08:00
Tree Xie
8bcb584aba
Revert "Improvements to how the X Axis is rendered" 2023-12-27 18:20:55 +08:00
50 changed files with 933 additions and 235 deletions

View file

@ -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

View file

@ -1,5 +1,7 @@
# go-charts
Clone from https://github.com/vicanso/go-charts
[![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/vicanso/go-charts/blob/master/LICENSE)
[![Build Status](https://github.com/vicanso/go-charts/workflows/Test/badge.svg)](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() {

View file

@ -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() {

View file

@ -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

View file

@ -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 {
@ -176,6 +176,7 @@ func (a *axisPainter) Render() (Box, error) {
unit := opt.Unit
if unit <= 0 {
unit = ceilFloatToInt(float64(dataCount) / float64(fitTextCount))
unit = chart.MaxInt(unit, opt.SplitNumber)
// 偶数

View file

@ -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) {
@ -53,7 +53,7 @@ func TestAxis(t *testing.T) {
}).Render()
return p.Bytes()
},
result: "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"600\" height=\"400\">\\n<path d=\"M 0 375\nL 0 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 85 375\nL 85 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 171 375\nL 171 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 257 375\nL 257 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 342 375\nL 342 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 428 375\nL 428 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 514 375\nL 514 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 600 375\nL 600 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 0 370\nL 600 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><text x=\"27\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Mon</text><text x=\"115\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Tue</text><text x=\"199\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Wed</text><text x=\"286\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Thu</text><text x=\"376\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Fri</text><text x=\"460\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Sat</text><text x=\"540\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Sun</text><path d=\"M 85 0\nL 85 370\" style=\"stroke-width:1;stroke:rgba(0,0,0,1.0);fill:none\"/><path d=\"M 171 0\nL 171 370\" style=\"stroke-width:1;stroke:rgba(0,0,0,1.0);fill:none\"/><path d=\"M 257 0\nL 257 370\" style=\"stroke-width:1;stroke:rgba(0,0,0,1.0);fill:none\"/><path d=\"M 342 0\nL 342 370\" style=\"stroke-width:1;stroke:rgba(0,0,0,1.0);fill:none\"/><path d=\"M 428 0\nL 428 370\" style=\"stroke-width:1;stroke:rgba(0,0,0,1.0);fill:none\"/><path d=\"M 514 0\nL 514 370\" style=\"stroke-width:1;stroke:rgba(0,0,0,1.0);fill:none\"/><path d=\"M 600 0\nL 600 370\" style=\"stroke-width:1;stroke:rgba(0,0,0,1.0);fill:none\"/></svg>",
result: "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"600\" height=\"400\">\\n<path d=\"M 0 375\nL 0 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 85 375\nL 85 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 171 375\nL 171 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 257 375\nL 257 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 342 375\nL 342 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 428 375\nL 428 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 514 375\nL 514 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 600 375\nL 600 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 0 370\nL 600 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><text x=\"27\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Mon</text><text x=\"115\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Tue</text><text x=\"199\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Wed</text><text x=\"286\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Thu</text><text x=\"376\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Fri</text><text x=\"460\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Sat</text><text x=\"544\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Sun</text><path d=\"M 85 0\nL 85 370\" style=\"stroke-width:1;stroke:rgba(0,0,0,1.0);fill:none\"/><path d=\"M 171 0\nL 171 370\" style=\"stroke-width:1;stroke:rgba(0,0,0,1.0);fill:none\"/><path d=\"M 257 0\nL 257 370\" style=\"stroke-width:1;stroke:rgba(0,0,0,1.0);fill:none\"/><path d=\"M 342 0\nL 342 370\" style=\"stroke-width:1;stroke:rgba(0,0,0,1.0);fill:none\"/><path d=\"M 428 0\nL 428 370\" style=\"stroke-width:1;stroke:rgba(0,0,0,1.0);fill:none\"/><path d=\"M 514 0\nL 514 370\" style=\"stroke-width:1;stroke:rgba(0,0,0,1.0);fill:none\"/><path d=\"M 600 0\nL 600 370\" style=\"stroke-width:1;stroke:rgba(0,0,0,1.0);fill:none\"/></svg>",
},
// 底部x轴文本居左
{
@ -72,7 +72,7 @@ func TestAxis(t *testing.T) {
}).Render()
return p.Bytes()
},
result: "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"600\" height=\"400\">\\n<path d=\"M 0 375\nL 0 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 100 375\nL 100 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 200 375\nL 200 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 300 375\nL 300 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 400 375\nL 400 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 500 375\nL 500 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 600 375\nL 600 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 0 370\nL 600 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><text x=\"-15\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Mon</text><text x=\"87\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Tue</text><text x=\"185\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Wed</text><text x=\"287\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Thu</text><text x=\"391\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Fri</text><text x=\"489\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Sat</text><text x=\"583\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Sun</text></svg>",
result: "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"600\" height=\"400\">\\n<path d=\"M 0 375\nL 0 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 100 375\nL 100 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 200 375\nL 200 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 300 375\nL 300 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 400 375\nL 400 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 500 375\nL 500 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 600 375\nL 600 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 0 370\nL 600 370\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><text x=\"-15\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Mon</text><text x=\"87\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Tue</text><text x=\"185\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Wed</text><text x=\"287\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Thu</text><text x=\"391\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Fri</text><text x=\"489\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Sat</text><text x=\"587\" y=\"395\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Sun</text></svg>",
},
// 左侧y轴
{
@ -155,7 +155,7 @@ func TestAxis(t *testing.T) {
}).Render()
return p.Bytes()
},
result: "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"600\" height=\"400\">\\n<path d=\"M 0 380\nL 0 375\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 85 380\nL 85 375\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 171 380\nL 171 375\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 257 380\nL 257 375\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 342 380\nL 342 375\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 428 380\nL 428 375\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 514 380\nL 514 375\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 600 380\nL 600 375\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 0 380\nL 600 380\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><text x=\"20\" y=\"375\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Mon --</text><text x=\"108\" y=\"375\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Tue --</text><text x=\"192\" y=\"375\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Wed --</text><text x=\"279\" y=\"375\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Thu --</text><text x=\"369\" y=\"375\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Fri --</text><text x=\"453\" y=\"375\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Sat --</text><text x=\"526\" y=\"375\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Sun --</text></svg>",
result: "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"600\" height=\"400\">\\n<path d=\"M 0 380\nL 0 375\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 85 380\nL 85 375\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 171 380\nL 171 375\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 257 380\nL 257 375\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 342 380\nL 342 375\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 428 380\nL 428 375\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 514 380\nL 514 375\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 600 380\nL 600 375\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 0 380\nL 600 380\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><text x=\"20\" y=\"375\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Mon --</text><text x=\"108\" y=\"375\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Tue --</text><text x=\"192\" y=\"375\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Wed --</text><text x=\"279\" y=\"375\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Thu --</text><text x=\"369\" y=\"375\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Fri --</text><text x=\"453\" y=\"375\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Sat --</text><text x=\"537\" y=\"375\" style=\"stroke-width:0;stroke:none;fill:rgba(70,70,70,1.0);font-size:15.3px;font-family:'Roboto Medium',sans-serif\">Sun --</text></svg>",
},
}

View file

@ -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{
// 居中的位置

File diff suppressed because one or more lines are too long

View file

@ -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

File diff suppressed because one or more lines are too long

View file

@ -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

View file

@ -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) {

View file

@ -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

File diff suppressed because one or more lines are too long

View file

@ -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
}

View file

@ -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
}

View file

@ -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 = `<!DOCTYPE html>

View file

@ -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
}

View file

@ -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
}

View file

@ -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)

View file

@ -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 {

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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{}

View file

@ -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) {

10
go.mod
View file

@ -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
)

20
go.sum
View file

@ -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=

View file

@ -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) {

View file

@ -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

File diff suppressed because one or more lines are too long

View file

@ -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)

File diff suppressed because one or more lines are too long

View file

@ -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) {

View file

@ -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) {

View file

@ -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
@ -615,20 +615,6 @@ func (p *Painter) TextFit(body string, x, y, width int, textAligns ...string) ch
return output
}
func isTick(totalRange int, unit int, index int) bool {
numTicks := (totalRange / unit) + 1
step := float64(totalRange-1) / float64(numTicks-1)
for i := int(float64(index) / step); i < numTicks; i++ {
value := int((float64(i) * step) + 0.5)
if value == index {
return true
} else if value > index {
break
}
}
return false
}
func (p *Painter) Ticks(opt TicksOption) *Painter {
if opt.Count <= 0 || opt.Length <= 0 {
return p
@ -652,7 +638,7 @@ func (p *Painter) Ticks(opt TicksOption) *Painter {
if index < first {
continue
}
if ! isTick(len(values), unit, index) {
if (index-first)%unit != 0 {
continue
}
if isVertical {
@ -688,13 +674,15 @@ func (p *Painter) MultiText(opt MultiTextOption) *Painter {
}
count := len(opt.TextList)
positionCenter := true
tickLimit := true
showIndex := opt.Unit / 2
if containsString([]string{
PositionLeft,
PositionTop,
}, opt.Position) {
positionCenter = false
count--
// 非居中
showIndex = 0
}
width := p.Width()
height := p.Height()
@ -702,7 +690,6 @@ func (p *Painter) MultiText(opt MultiTextOption) *Painter {
isVertical := opt.Orient == OrientVertical
if isVertical {
values = autoDivide(height, count)
tickLimit = false
} else {
values = autoDivide(width, count)
}
@ -712,7 +699,7 @@ func (p *Painter) MultiText(opt MultiTextOption) *Painter {
if index < opt.First {
continue
}
if opt.Unit != 0 && tickLimit && ! isTick(len(opt.TextList)-opt.First, opt.Unit, index-opt.First) {
if opt.Unit != 0 && (index-opt.First)%opt.Unit != showIndex {
continue
}
if isTextRotation {
@ -737,11 +724,7 @@ func (p *Painter) MultiText(opt MultiTextOption) *Painter {
x = 0
}
} else {
if index == len(opt.TextList) - 1 {
x = start - box.Width() + 10
} else {
x = start - box.Width()>>1
}
x = start - box.Width()>>1
}
x += offset.Left
y += offset.Top
@ -766,6 +749,7 @@ func (p *Painter) Grid(opt GridOption) *Painter {
x1 := 0
y1 := 0
if isVertical {
x0 = v
x1 = v
y1 = height
@ -819,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()
@ -834,3 +860,7 @@ func (p *Painter) LegendLineDot(box Box) *Painter {
p.FillStroke()
return p
}
func (p *Painter) GetRenderer() chart.Renderer {
return p.render
}

View file

@ -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("<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"400\" height=\"300\">\\n<path d=\"M 15 10\nL 25 10\nL 25 10\nA 5 5 90.00 0 1 30 15\nL 30 145\nL 30 145\nA 5 5 90.00 0 1 25 150\nL 15 150\nL 15 150\nA 5 5 90.00 0 1 10 145\nL 10 15\nL 10 15\nA 5 5 90.00 0 1 15 10\nZ\" style=\"stroke-width:1;stroke:rgba(255,255,255,1.0);fill:rgba(255,255,255,1.0)\"/><path d=\"\" style=\"stroke-width:1;stroke:rgba(255,255,255,1.0);fill:rgba(255,255,255,1.0)\"/></svg>", string(buf))
}
func TestPainterTextFit(t *testing.T) {
assert := assert.New(t)
p, err := NewPainter(PainterOptions{

View file

@ -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
}

File diff suppressed because one or more lines are too long

View file

@ -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)
}
}
}

View file

@ -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

View file

@ -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 {

View file

@ -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 {

View file

@ -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"

View file

@ -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 {

View file

@ -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) {

View file

@ -40,7 +40,7 @@ type XAxisOption struct {
FontSize float64
// The flag for show axis, set this to *false will hide axis
Show *bool
// Number of segments that the axis is split into. Note that this number serves only as a recommendation to avoid writing overlap.
// Number of segments that the axis is split into. Note that this number serves only as a recommendation.
SplitNumber int
// The position of axis, it can be 'top' or 'bottom'
Position string
@ -55,8 +55,6 @@ type XAxisOption struct {
// The offset of label
LabelOffset Box
isValueAxis bool
// This value overrides SplitNumber, specifying directly the frequency at which the axis is split into, higher numbers result in less ticks
Unit int
}
const defaultXAxisHeight = 30
@ -92,7 +90,6 @@ func (opt *XAxisOption) ToAxisOption() AxisOption {
TextRotation: opt.TextRotation,
LabelOffset: opt.LabelOffset,
FirstAxis: opt.FirstAxis,
Unit: opt.Unit,
}
if opt.isValueAxis {
axisOpt.SplitLineShow = true

View file

@ -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
}