test: add test for axis
This commit is contained in:
parent
635e440e85
commit
d3c6649cd9
12 changed files with 145 additions and 40 deletions
|
|
@ -33,7 +33,7 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
values := [][]float64{
|
||||
values := [][]float64{
|
||||
{
|
||||
120,
|
||||
132,
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
values := [][]float64{
|
||||
values := [][]float64{
|
||||
{
|
||||
120,
|
||||
132,
|
||||
|
|
|
|||
7
axis.go
7
axis.go
|
|
@ -81,7 +81,10 @@ func (a *axisPainter) Render() (Box, error) {
|
|||
opt := a.opt
|
||||
top := a.p
|
||||
theme := opt.Theme
|
||||
if opt.Show != nil && !*opt.Show {
|
||||
if theme == nil {
|
||||
theme = top.theme
|
||||
}
|
||||
if isFalse(opt.Show) {
|
||||
return BoxZero, nil
|
||||
}
|
||||
|
||||
|
|
@ -121,7 +124,7 @@ func (a *axisPainter) Render() (Box, error) {
|
|||
tickCount := dataCount
|
||||
|
||||
boundaryGap := true
|
||||
if opt.BoundaryGap != nil && !*opt.BoundaryGap {
|
||||
if isFalse(opt.BoundaryGap) {
|
||||
boundaryGap = false
|
||||
}
|
||||
isVertical := opt.Position == PositionLeft ||
|
||||
|
|
|
|||
129
axis_test.go
Normal file
129
axis_test.go
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
// MIT License
|
||||
|
||||
// Copyright (c) 2022 Tree Xie
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
package charts
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/wcharczuk/go-chart/v2/drawing"
|
||||
)
|
||||
|
||||
func TestAxis(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
tests := []struct {
|
||||
render func(*Painter) ([]byte, error)
|
||||
result string
|
||||
}{
|
||||
// 底部x轴
|
||||
{
|
||||
render: func(p *Painter) ([]byte, error) {
|
||||
_, _ = NewAxisPainter(p, AxisOption{
|
||||
Data: []string{
|
||||
"Mon",
|
||||
"Tue",
|
||||
"Wed",
|
||||
"Thu",
|
||||
"Fri",
|
||||
"Sat",
|
||||
"Sun",
|
||||
},
|
||||
}).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=\"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></svg>",
|
||||
},
|
||||
// 底部x轴文本居左
|
||||
{
|
||||
render: func(p *Painter) ([]byte, error) {
|
||||
_, _ = NewAxisPainter(p, AxisOption{
|
||||
Data: []string{
|
||||
"Mon",
|
||||
"Tue",
|
||||
"Wed",
|
||||
"Thu",
|
||||
"Fri",
|
||||
"Sat",
|
||||
"Sun",
|
||||
},
|
||||
BoundaryGap: FalseFlag(),
|
||||
}).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=\"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轴
|
||||
{
|
||||
render: func(p *Painter) ([]byte, error) {
|
||||
_, _ = NewAxisPainter(p, AxisOption{
|
||||
Data: []string{
|
||||
"Mon",
|
||||
"Tue",
|
||||
"Wed",
|
||||
"Thu",
|
||||
"Fri",
|
||||
"Sat",
|
||||
"Sun",
|
||||
},
|
||||
Position: PositionLeft,
|
||||
}).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 36 0\nL 41 0\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 36 57\nL 41 57\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 36 114\nL 41 114\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 36 171\nL 41 171\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 36 228\nL 41 228\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 36 285\nL 41 285\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 36 342\nL 41 342\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 36 400\nL 41 400\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 41 0\nL 41 400\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><text x=\"0\" y=\"35\" 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=\"4\" y=\"92\" 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=\"0\" y=\"149\" 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=\"4\" y=\"206\" 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=\"13\" y=\"263\" 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=\"8\" y=\"320\" 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=\"4\" y=\"378\" 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轴居中
|
||||
{
|
||||
render: func(p *Painter) ([]byte, error) {
|
||||
_, _ = NewAxisPainter(p, AxisOption{
|
||||
Data: []string{
|
||||
"Mon",
|
||||
"Tue",
|
||||
"Wed",
|
||||
"Thu",
|
||||
"Fri",
|
||||
"Sat",
|
||||
"Sun",
|
||||
},
|
||||
Position: PositionLeft,
|
||||
BoundaryGap: FalseFlag(),
|
||||
SplitLineShow: true,
|
||||
SplitLineColor: drawing.ColorBlack,
|
||||
}).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 36 0\nL 41 0\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 36 66\nL 41 66\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 36 133\nL 41 133\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 36 200\nL 41 200\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 36 266\nL 41 266\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 36 333\nL 41 333\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 36 400\nL 41 400\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><path d=\"M 41 0\nL 41 400\" style=\"stroke-width:1;stroke:rgba(110,112,121,1.0);fill:none\"/><text x=\"0\" y=\"7\" 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=\"4\" y=\"73\" 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=\"0\" y=\"140\" 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=\"4\" y=\"207\" 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=\"13\" y=\"273\" 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=\"8\" y=\"340\" 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=\"4\" y=\"407\" 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 41 0\nL 600 0\" style=\"stroke-width:1;stroke:rgba(0,0,0,1.0);fill:none\"/><path d=\"M 41 66\nL 600 66\" style=\"stroke-width:1;stroke:rgba(0,0,0,1.0);fill:none\"/><path d=\"M 41 133\nL 600 133\" style=\"stroke-width:1;stroke:rgba(0,0,0,1.0);fill:none\"/><path d=\"M 41 200\nL 600 200\" style=\"stroke-width:1;stroke:rgba(0,0,0,1.0);fill:none\"/><path d=\"M 41 266\nL 600 266\" style=\"stroke-width:1;stroke:rgba(0,0,0,1.0);fill:none\"/><path d=\"M 41 333\nL 600 333\" style=\"stroke-width:1;stroke:rgba(0,0,0,1.0);fill:none\"/><path d=\"M 41 400\nL 600 400\" style=\"stroke-width:1;stroke:rgba(0,0,0,1.0);fill:none\"/></svg>",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
p, err := NewPainter(PainterOptions{
|
||||
Type: ChartOutputSVG,
|
||||
Width: 600,
|
||||
Height: 400,
|
||||
}, PainterThemeOption(defaultTheme))
|
||||
assert.Nil(err)
|
||||
data, err := tt.render(p)
|
||||
assert.Nil(err)
|
||||
assert.Equal(tt.result, string(data))
|
||||
}
|
||||
}
|
||||
|
|
@ -115,5 +115,4 @@ func main() {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -430,7 +430,7 @@ func main() {
|
|||
Left: 1,
|
||||
Right: p.Width() - 1,
|
||||
Bottom: top + 30,
|
||||
})), charts.LegendPainterOption{
|
||||
})), charts.LegendOption{
|
||||
Left: "10",
|
||||
Data: []string{
|
||||
"Email",
|
||||
|
|
@ -449,7 +449,7 @@ func main() {
|
|||
Left: 1,
|
||||
Right: p.Width() - 1,
|
||||
Bottom: top + 30,
|
||||
})), charts.LegendPainterOption{
|
||||
})), charts.LegendOption{
|
||||
Left: charts.PositionRight,
|
||||
Data: []string{
|
||||
"Email",
|
||||
|
|
@ -470,7 +470,7 @@ func main() {
|
|||
Left: 1,
|
||||
Right: p.Width() - 1,
|
||||
Bottom: top + 100,
|
||||
})), charts.LegendPainterOption{
|
||||
})), charts.LegendOption{
|
||||
Top: "10",
|
||||
Data: []string{
|
||||
"Email",
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ func (l *legendPainter) Render() (Box, error) {
|
|||
opt := l.opt
|
||||
theme := opt.Theme
|
||||
if opt.IsEmpty() ||
|
||||
(opt.Show != nil && !*opt.Show) {
|
||||
isFalse(opt.Show) {
|
||||
return BoxZero, nil
|
||||
}
|
||||
if theme == nil {
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ func (l *lineChart) render(result *defaultRenderResult, seriesList SeriesList) (
|
|||
p := l.p
|
||||
opt := l.opt
|
||||
boundaryGap := true
|
||||
if opt.XAxis.BoundaryGap != nil && !*opt.XAxis.BoundaryGap {
|
||||
if isFalse(opt.XAxis.BoundaryGap) {
|
||||
boundaryGap = false
|
||||
}
|
||||
|
||||
|
|
|
|||
10
mark_line.go
10
mark_line.go
|
|
@ -105,13 +105,3 @@ func (m *markLinePainter) Render() (Box, error) {
|
|||
}
|
||||
return BoxZero, nil
|
||||
}
|
||||
|
||||
func markLineRender(opt markLineRenderOption) {
|
||||
// d := opt.Draw
|
||||
// s := opt.Series
|
||||
// if len(s.MarkLine.Data) == 0 {
|
||||
// return
|
||||
// }
|
||||
// r := d.Render
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ type Painter struct {
|
|||
}
|
||||
|
||||
type PainterOptions struct {
|
||||
// Draw type, "svg" or "png", default type is "svg"
|
||||
// Draw type, "svg" or "png", default type is "png"
|
||||
Type string
|
||||
// The width of draw painter
|
||||
Width int
|
||||
|
|
@ -628,7 +628,7 @@ func (p *Painter) MultiText(opt MultiTextOption) *Painter {
|
|||
values = autoDivide(width, count)
|
||||
}
|
||||
for index, text := range opt.TextList {
|
||||
if index%opt.Unit != 0 {
|
||||
if opt.Unit != 0 && index%opt.Unit != 0 {
|
||||
continue
|
||||
}
|
||||
box := p.MeasureText(text)
|
||||
|
|
|
|||
10
range.go
10
range.go
|
|
@ -115,13 +115,3 @@ func (r *axisRange) GetRange(index int) (float64, float64) {
|
|||
func (r *axisRange) AutoDivide() []int {
|
||||
return autoDivide(r.size, r.divideCount)
|
||||
}
|
||||
|
||||
func (r *axisRange) getWidth(value float64) int {
|
||||
v := value / (r.max - r.min)
|
||||
// 移至居中
|
||||
if r.boundary &&
|
||||
r.divideCount != 0 {
|
||||
v += 1 / float64(r.divideCount*2)
|
||||
}
|
||||
return int(v * float64(r.size))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,12 +140,6 @@ func (sl SeriesList) init() {
|
|||
}
|
||||
}
|
||||
|
||||
func (sl SeriesList) reverse() {
|
||||
for i, j := 0, len(sl)-1; i < j; i, j = i+1, j-1 {
|
||||
sl[i], sl[j] = sl[j], sl[i]
|
||||
}
|
||||
}
|
||||
|
||||
func (sl SeriesList) Filter(chartType string) SeriesList {
|
||||
arr := make(SeriesList, 0)
|
||||
for index, item := range sl {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue