feat: support make point and make line

This commit is contained in:
vicanso 2022-02-10 23:24:30 +08:00
parent fd05250305
commit e558634dda
16 changed files with 308 additions and 51 deletions

25
axis.go
View file

@ -68,6 +68,10 @@ type axis struct {
data *AxisDataList
style *AxisOption
}
type axisMeasurement struct {
Width int
Height int
}
func NewAxis(d *Draw, data AxisDataList, style AxisOption) *axis {
return &axis{
@ -379,7 +383,7 @@ func (a *axis) axisTick(opt *axisRenderOption) {
}
}
func (a *axis) axisMeasureTextMaxWidthHeight() (int, int) {
func (a *axis) measureTextMaxWidthHeight() (int, int) {
d := a.d
r := d.Render
s := a.style.Style(d.Font)
@ -389,18 +393,21 @@ func (a *axis) axisMeasureTextMaxWidthHeight() (int, int) {
return measureTextMaxWidthHeight(data.TextList(), r)
}
// measureAxis returns the measurement of axis.
// If the position is left or right, it will be textMaxWidth + labelMargin + tickLength.
// If the position is top or bottom, it will be textMaxHeight + labelMargin + tickLength.
func (a *axis) measureAxis() int {
// measure returns the measurement of axis.
// Width will be textMaxWidth + labelMargin + tickLength for position left or right.
// Height will be textMaxHeight + labelMargin + tickLength for position top or bottom.
func (a *axis) measure() axisMeasurement {
style := a.style
value := style.GetLabelMargin() + style.GetTickLength()
textMaxWidth, textMaxHeight := a.axisMeasureTextMaxWidthHeight()
textMaxWidth, textMaxHeight := a.measureTextMaxWidthHeight()
info := axisMeasurement{}
if style.Position == PositionLeft ||
style.Position == PositionRight {
return textMaxWidth + value
info.Width = textMaxWidth + value
} else {
info.Height = textMaxHeight + value
}
return textMaxHeight + value
return info
}
// Render renders the axis for chart
@ -409,7 +416,7 @@ func (a *axis) Render() {
if isFalse(style.Show) {
return
}
textMaxWidth, textMaxHeight := a.axisMeasureTextMaxWidthHeight()
textMaxWidth, textMaxHeight := a.measureTextMaxWidthHeight()
opt := &axisRenderOption{
textMaxWith: textMaxWidth,
textMaxHeight: textMaxHeight,

View file

@ -247,13 +247,13 @@ func TestMeasureAxis(t *testing.T) {
FontSize: 12,
Font: f,
Position: PositionLeft,
}).measureAxis()
}).measure().Width
assert.Equal(44, width)
height := NewAxis(d, data, AxisOption{
FontSize: 12,
Font: f,
Position: PositionTop,
}).measureAxis()
}).measure().Height
assert.Equal(28, height)
}

View file

@ -26,7 +26,7 @@ import (
"github.com/wcharczuk/go-chart/v2"
)
func barChartRender(opt ChartOption, result *basicRenderResult) (*Draw, error) {
func barChartRender(opt ChartOption, result *basicRenderResult) ([]*markPointRenderOption, error) {
d, err := NewDraw(DrawOption{
Parent: result.d,
@ -57,10 +57,29 @@ func barChartRender(opt ChartOption, result *basicRenderResult) (*Draw, error) {
r := d.Render
for i, series := range opt.SeriesList {
markPointRenderOptions := make([]*markPointRenderOption, 0)
for i, s := range opt.SeriesList {
// 由于series是for range为同一个数据因此需要clone
// 后续需要使用如mark point
series := s
yRange := result.getYRange(series.YAxisIndex)
points := make([]Point, len(series.Data))
seriesColor := theme.GetSeriesColor(i)
index := series.index
if index == 0 {
index = i
}
seriesColor := theme.GetSeriesColor(index)
// mark line
markLineRender(&markLineRenderOption{
Draw: d,
FillColor: seriesColor,
FontColor: theme.GetTextColor(),
StrokeColor: seriesColor,
Font: opt.Font,
Series: &series,
Range: yRange,
})
for j, item := range series.Data {
x0, _ := xRange.GetRange(j)
x := int(x0)
@ -105,7 +124,9 @@ func barChartRender(opt ChartOption, result *basicRenderResult) (*Draw, error) {
textBox := r.MeasureText(text)
d.text(text, x+(barWidth-textBox.Width())>>1, barMaxHeight-h-5)
}
markPointRender(d, markPointRenderOption{
markPointRenderOptions = append(markPointRenderOptions, &markPointRenderOption{
Draw: d,
FillColor: seriesColor,
Font: opt.Font,
Points: points,
@ -113,5 +134,5 @@ func barChartRender(opt ChartOption, result *basicRenderResult) (*Draw, error) {
})
}
return result.d, nil
return markPointRenderOptions, nil
}

View file

@ -80,6 +80,14 @@ func (o *ChartOption) FillDefault(theme string) {
if o.BackgroundColor.IsZero() {
o.BackgroundColor = t.GetBackgroundColor()
}
if o.Padding.IsZero() {
o.Padding = chart.Box{
Top: 20,
Right: 10,
Bottom: 10,
Left: 10,
}
}
// 标题的默认值
if o.Title.Style.FontColor.IsZero() {
@ -110,7 +118,7 @@ func (o *ChartOption) FillDefault(theme string) {
o.Title.SubtextStyle.Font = o.Font
}
o.Legend.Theme = theme
o.Legend.theme = theme
if o.Legend.Style.FontSize == 0 {
o.Legend.Style.FontSize = 10
}
@ -238,13 +246,14 @@ func Render(opt ChartOption) (*Draw, error) {
if err != nil {
return nil, err
}
markPointRenderOptions := make([]*markPointRenderOption, 0)
fns := []func() error{
// pie render
func() error {
if !isPieChart {
return nil
}
_, err := pieChartRender(opt, result)
err := pieChartRender(opt, result)
return err
},
// bar render
@ -255,8 +264,12 @@ func Render(opt ChartOption) (*Draw, error) {
}
o := opt
o.SeriesList = barSeries
_, err := barChartRender(o, result)
options, err := barChartRender(o, result)
if err != nil {
return err
}
markPointRenderOptions = append(markPointRenderOptions, options...)
return nil
},
// line render
func() error {
@ -266,14 +279,26 @@ func Render(opt ChartOption) (*Draw, error) {
}
o := opt
o.SeriesList = lineSeries
_, err := lineChartRender(o, result)
options, err := lineChartRender(o, result)
if err != nil {
return err
}
markPointRenderOptions = append(markPointRenderOptions, options...)
return nil
},
// legend需要在顶层因此最后render
// legend需要在顶层因此此处render
func() error {
_, err := NewLegend(result.d, opt.Legend).Render()
return err
},
// mark point最后render
func() error {
// mark point render不会出错
for _, opt := range markPointRenderOptions {
markPointRender(opt)
}
return nil
},
}
for _, fn := range fns {
@ -296,6 +321,7 @@ func Render(opt ChartOption) (*Draw, error) {
}
func chartBasicRender(opt *ChartOption) (*basicRenderResult, error) {
opt.FillDefault(opt.Theme)
d, err := NewDraw(
DrawOption{
Type: opt.Type,
@ -309,7 +335,6 @@ func chartBasicRender(opt *ChartOption) (*basicRenderResult, error) {
return nil, err
}
opt.FillDefault(opt.Theme)
if len(opt.YAxisList) > 2 {
return nil, errors.New("y axis should not be gt 2")
}

20
draw.go
View file

@ -161,7 +161,9 @@ func (d *Draw) pin(x, y, width int) {
delta := 2*math.Pi - 2*angle
d.arcTo(x, y, r, r, startAngle, delta)
d.lineTo(x, y)
d.Render.Fill()
d.Render.Close()
d.Render.FillStroke()
startX := x - int(r)
startY := y
endX := x + int(r)
@ -173,7 +175,8 @@ func (d *Draw) pin(x, y, width int) {
cx := x
cy := y + int(r*2.5)
d.Render.QuadCurveTo(cx+left, cy+top, endX+left, endY+top)
d.Render.Stroke()
d.Render.Close()
d.Render.Fill()
}
func (d *Draw) arrowLeft(x, y, width, height int) {
@ -226,7 +229,20 @@ func (d *Draw) arrow(x, y, width, height int, direction string) {
d.lineTo(x0+dx, y0+halfHeight)
d.lineTo(x0, y0)
}
d.Render.FillStroke()
}
func (d *Draw) makeLine(x, y, width int) {
arrowWidth := 16
arrowHeight := 10
endX := x + width
d.circle(3, x, y)
d.Render.Fill()
d.moveTo(x+5, y)
d.lineTo(endX-arrowWidth, y)
d.Render.Stroke()
d.Render.SetStrokeDashArray([]float64{})
d.arrowRight(endX, y, arrowWidth, arrowHeight)
}
func (d *Draw) circle(radius float64, x, y int) {

View file

@ -259,7 +259,7 @@ func TestDraw(t *testing.T) {
}.WriteToRenderer(d.Render)
d.pin(30, 30, 30)
},
result: "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"400\" height=\"300\">\\n<path d=\"M 32 47\nA 15 15 330.00 1 1 38 47\nL 35 33\" style=\"stroke-width:1;stroke:rgba(84,112,198,1.0);fill:rgba(84,112,198,1.0)\"/><path d=\"M 20 33\nQ35,70 50,33\" style=\"stroke-width:1;stroke:rgba(84,112,198,1.0);fill:rgba(84,112,198,1.0)\"/></svg>",
result: "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"400\" height=\"300\">\\n<path d=\"M 32 47\nA 15 15 330.00 1 1 38 47\nL 35 33\nZ\" style=\"stroke-width:1;stroke:rgba(84,112,198,1.0);fill:rgba(84,112,198,1.0)\"/><path d=\"M 20 33\nQ35,70 50,33\nZ\" style=\"stroke-width:1;stroke:rgba(84,112,198,1.0);fill:rgba(84,112,198,1.0)\"/></svg>",
},
// arrow left
{
@ -349,6 +349,32 @@ func TestDraw(t *testing.T) {
},
result: "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"400\" height=\"300\">\\n<path d=\"M 30 24\nL 35 40\nL 40 24\nL 35 30\nL 30 24\" style=\"stroke-width:1;stroke:rgba(84,112,198,1.0);fill:rgba(84,112,198,1.0)\"/></svg>",
},
// mark line
{
fn: func(d *Draw) {
chart.Style{
StrokeWidth: 1,
StrokeColor: drawing.Color{
R: 84,
G: 112,
B: 198,
A: 255,
},
FillColor: drawing.Color{
R: 84,
G: 112,
B: 198,
A: 255,
},
StrokeDashArray: []float64{
4,
2,
},
}.WriteToRenderer(d.Render)
d.makeLine(0, 20, 300)
},
result: "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"400\" height=\"300\">\\n<circle cx=\"5\" cy=\"30\" r=\"3\" style=\"stroke-width:1;stroke:rgba(84,112,198,1.0);fill:rgba(84,112,198,1.0)\"/><path stroke-dasharray=\"4.0, 2.0\" d=\"\" style=\"stroke-width:1;stroke:rgba(84,112,198,1.0);fill:rgba(84,112,198,1.0)\"/><path stroke-dasharray=\"4.0, 2.0\" d=\"M 10 30\nL 289 30\" style=\"stroke-width:1;stroke:rgba(84,112,198,1.0);fill:rgba(84,112,198,1.0)\"/><path d=\"M 289 25\nL 305 30\nL 289 35\nL 294 30\nL 289 25\" style=\"stroke-width:1;stroke:rgba(84,112,198,1.0);fill:rgba(84,112,198,1.0)\"/></svg>",
},
}
for _, tt := range tests {
d, err := NewDraw(DrawOption{

View file

@ -30,7 +30,7 @@ import (
)
type LegendOption struct {
Theme string
theme string
// Legend show flag, if nil or true, the legend will be shown
Show *bool
// Legend text style
@ -67,7 +67,7 @@ func (l *legend) Render() (chart.Box, error) {
if len(opt.Data) == 0 || isFalse(opt.Show) {
return chart.BoxZero, nil
}
theme := NewTheme(opt.Theme)
theme := NewTheme(opt.theme)
padding := opt.Style.Padding
legendDraw, err := NewDraw(DrawOption{
Parent: d,

View file

@ -27,7 +27,7 @@ import (
"github.com/wcharczuk/go-chart/v2/drawing"
)
func lineChartRender(opt ChartOption, result *basicRenderResult) (*Draw, error) {
func lineChartRender(opt ChartOption, result *basicRenderResult) ([]*markPointRenderOption, error) {
theme := NewTheme(opt.Theme)
@ -44,9 +44,29 @@ func lineChartRender(opt ChartOption, result *basicRenderResult) (*Draw, error)
r := d.Render
xRange := result.xRange
for i, series := range opt.SeriesList {
markPointRenderOptions := make([]*markPointRenderOption, 0)
for i, s := range opt.SeriesList {
// 由于series是for range为同一个数据因此需要clone
// 后续需要使用如mark point
series := s
index := series.index
if index == 0 {
index = i
}
seriesColor := theme.GetSeriesColor(index)
yRange := result.getYRange(series.YAxisIndex)
points := make([]Point, len(series.Data))
// mark line
markLineRender(&markLineRenderOption{
Draw: d,
FillColor: seriesColor,
FontColor: theme.GetTextColor(),
StrokeColor: seriesColor,
Font: opt.Font,
Series: &series,
Range: yRange,
})
for j, item := range series.Data {
y := yRange.getRestHeight(item.Value)
@ -71,11 +91,7 @@ func lineChartRender(opt ChartOption, result *basicRenderResult) (*Draw, error)
textBox := r.MeasureText(text)
d.text(text, x-textBox.Width()>>1, y-5)
}
index := series.index
if index == 0 {
index = i
}
seriesColor := theme.GetSeriesColor(index)
dotFillColor := drawing.ColorWhite
if theme.IsDark() {
dotFillColor = seriesColor
@ -88,7 +104,8 @@ func lineChartRender(opt ChartOption, result *basicRenderResult) (*Draw, error)
DotFillColor: dotFillColor,
})
// draw mark point
markPointRender(d, markPointRenderOption{
markPointRenderOptions = append(markPointRenderOptions, &markPointRenderOption{
Draw: d,
FillColor: seriesColor,
Font: opt.Font,
Points: points,
@ -96,5 +113,5 @@ func lineChartRender(opt ChartOption, result *basicRenderResult) (*Draw, error)
})
}
return result.d, nil
return markPointRenderOptions, nil
}

92
mark_line.go Normal file
View file

@ -0,0 +1,92 @@
// 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 (
"github.com/golang/freetype/truetype"
"github.com/wcharczuk/go-chart/v2"
"github.com/wcharczuk/go-chart/v2/drawing"
)
func NewMarkLine(markLineTypes ...string) SeriesMarkLine {
data := make([]SeriesMarkLineData, len(markLineTypes))
for index, t := range markLineTypes {
data[index] = SeriesMarkLineData{
Type: t,
}
}
return SeriesMarkLine{
Data: data,
}
}
type markLineRenderOption struct {
Draw *Draw
FillColor drawing.Color
FontColor drawing.Color
StrokeColor drawing.Color
Font *truetype.Font
Series *Series
Range *Range
}
func markLineRender(opt *markLineRenderOption) {
d := opt.Draw
s := opt.Series
if len(s.MarkLine.Data) == 0 {
return
}
r := d.Render
summary := s.Summary()
for _, markLine := range s.MarkLine.Data {
// 由于mark line会修改style因此每次重新设置
chart.Style{
FillColor: opt.FillColor,
FontColor: opt.FontColor,
FontSize: labelFontSize,
StrokeColor: opt.StrokeColor,
StrokeWidth: 1,
Font: opt.Font,
StrokeDashArray: []float64{
4,
2,
},
}.WriteToRenderer(r)
value := float64(0)
switch markLine.Type {
case SeriesMarkDataTypeMax:
value = summary.MaxValue
case SeriesMarkDataTypeMin:
value = summary.MinValue
default:
value = summary.AverageValue
}
y := opt.Range.getRestHeight(value)
width := d.Box.Width()
text := commafWithDigits(value)
textBox := r.MeasureText(text)
d.makeLine(0, y, width)
d.text(text, width, y+textBox.Height()>>1-2)
}
}

View file

@ -28,14 +28,28 @@ import (
"github.com/wcharczuk/go-chart/v2/drawing"
)
func NewMarkPoint(markPointTypes ...string) SeriesMarkPoint {
data := make([]SeriesMarkPointData, len(markPointTypes))
for index, t := range markPointTypes {
data[index] = SeriesMarkPointData{
Type: t,
}
}
return SeriesMarkPoint{
Data: data,
}
}
type markPointRenderOption struct {
Draw *Draw
FillColor drawing.Color
Font *truetype.Font
Series *Series
Points []Point
}
func markPointRender(d *Draw, opt markPointRenderOption) {
func markPointRender(opt *markPointRenderOption) {
d := opt.Draw
s := opt.Series
if len(s.MarkPoint.Data) == 0 {
return
@ -54,7 +68,7 @@ func markPointRender(d *Draw, opt markPointRenderOption) {
// 设置文本样式
chart.Style{
FontColor: NewTheme(ThemeDark).GetTextColor(),
FontSize: 10,
FontSize: labelFontSize,
StrokeWidth: 1,
Font: opt.Font,
}.WriteTextOptionsToRenderer(r)
@ -62,7 +76,7 @@ func markPointRender(d *Draw, opt markPointRenderOption) {
p := points[summary.MinIndex]
value := summary.MinValue
switch markPointData.Type {
case SeriesMarkPointDataTypeMax:
case SeriesMarkDataTypeMax:
p = points[summary.MaxIndex]
value = summary.MaxValue
}

View file

@ -41,14 +41,14 @@ func getPieStyle(theme *Theme, index int) chart.Style {
}
func pieChartRender(opt ChartOption, result *basicRenderResult) (*Draw, error) {
func pieChartRender(opt ChartOption, result *basicRenderResult) error {
d, err := NewDraw(DrawOption{
Parent: result.d,
}, PaddingOption(chart.Box{
Top: result.titleBox.Height(),
}))
if err != nil {
return nil, err
return err
}
values := make([]float64, len(opt.SeriesList))
@ -155,5 +155,5 @@ func pieChartRender(opt ChartOption, result *basicRenderResult) (*Draw, error) {
d.text(text, x, y)
}
}
return result.d, nil
return nil
}

View file

@ -54,9 +54,11 @@ func NewRange(min, max float64, divideCount int) Range {
unit = int((r/float64(divideCount))/float64(unit))*unit + unit
if min != 0 {
isLessThanZero := min < 0
min = float64(int(min/float64(unit)) * unit)
// 如果是小于0int的时候向上取整了因此调整
if min < 0 {
if min < 0 ||
(isLessThanZero && min == 0) {
min -= float64(unit)
}
}

View file

@ -63,8 +63,9 @@ type SeriesLabel struct {
}
const (
SeriesMarkPointDataTypeMax = "max"
SeriesMarkPointDataTypeMin = "min"
SeriesMarkDataTypeMax = "max"
SeriesMarkDataTypeMin = "min"
SeriesMarkDataTypeAverage = "average"
)
type SeriesMarkPointData struct {
@ -74,6 +75,12 @@ type SeriesMarkPoint struct {
SymbolSize int
Data []SeriesMarkPointData
}
type SeriesMarkLineData struct {
Type string
}
type SeriesMarkLine struct {
Data []SeriesMarkLineData
}
type Series struct {
index int
Type string
@ -85,6 +92,7 @@ type Series struct {
// Radius of Pie chart, e.g.: 40%
Radius string
MarkPoint SeriesMarkPoint
MarkLine SeriesMarkLine
}
type seriesSummary struct {

View file

@ -77,8 +77,7 @@ func drawXAxis(p *Draw, opt *XAxisOption, yAxisCount int) (int, *Range, error) {
}
axis := NewAxis(dXAxis, data, style)
axis.Render()
return axis.measureAxis(), &Range{
return axis.measure().Height, &Range{
divideCount: len(opt.Data),
Min: 0,
Max: max,

View file

@ -62,7 +62,7 @@ func drawYAxis(p *Draw, opt *ChartOption, axisIndex, xAxisHeight int, padding ch
SplitLineColor: theme.GetAxisSplitLineColor(),
SplitLineShow: true,
}
width := NewAxis(p, data, style).measureAxis()
width := NewAxis(p, data, style).measure().Width
yAxisCount := len(opt.YAxisList)
boxWidth := p.Box.Width()

View file

@ -42,6 +42,7 @@ func TestDrawYAxis(t *testing.T) {
tests := []struct {
newDraw func() *Draw
newOption func() *ChartOption
axisIndex int
xAxisHeight int
result string
}{
@ -70,11 +71,40 @@ func TestDrawYAxis(t *testing.T) {
},
result: "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"400\" height=\"300\">\\n<path d=\"M 50 10\nL 50 290\" style=\"stroke-width:1;stroke:none;fill:none\"/><path d=\"M 50 10\nL 390 10\" style=\"stroke-width:1;stroke:rgba(224,230,242,1.0);fill:none\"/><path d=\"M 50 57\nL 390 57\" style=\"stroke-width:1;stroke:rgba(224,230,242,1.0);fill:none\"/><path d=\"M 50 104\nL 390 104\" style=\"stroke-width:1;stroke:rgba(224,230,242,1.0);fill:none\"/><path d=\"M 50 151\nL 390 151\" style=\"stroke-width:1;stroke:rgba(224,230,242,1.0);fill:none\"/><path d=\"M 50 198\nL 390 198\" style=\"stroke-width:1;stroke:rgba(224,230,242,1.0);fill:none\"/><path d=\"M 50 244\nL 390 244\" style=\"stroke-width:1;stroke:rgba(224,230,242,1.0);fill:none\"/><text x=\"36\" y=\"294\" style=\"stroke-width:0;stroke:none;fill:rgba(110,112,121,1.0);font-size:12.8px;font-family:'Roboto Medium',sans-serif\">0</text><text x=\"18\" y=\"248\" style=\"stroke-width:0;stroke:none;fill:rgba(110,112,121,1.0);font-size:12.8px;font-family:'Roboto Medium',sans-serif\">3.33</text><text x=\"18\" y=\"202\" style=\"stroke-width:0;stroke:none;fill:rgba(110,112,121,1.0);font-size:12.8px;font-family:'Roboto Medium',sans-serif\">6.66</text><text x=\"29\" y=\"155\" style=\"stroke-width:0;stroke:none;fill:rgba(110,112,121,1.0);font-size:12.8px;font-family:'Roboto Medium',sans-serif\">10</text><text x=\"11\" y=\"108\" style=\"stroke-width:0;stroke:none;fill:rgba(110,112,121,1.0);font-size:12.8px;font-family:'Roboto Medium',sans-serif\">13.33</text><text x=\"11\" y=\"61\" style=\"stroke-width:0;stroke:none;fill:rgba(110,112,121,1.0);font-size:12.8px;font-family:'Roboto Medium',sans-serif\">16.66</text><text x=\"29\" y=\"14\" style=\"stroke-width:0;stroke:none;fill:rgba(110,112,121,1.0);font-size:12.8px;font-family:'Roboto Medium',sans-serif\">20</text></svg>",
},
{
newDraw: newDraw,
newOption: func() *ChartOption {
return &ChartOption{
YAxisList: []YAxisOption{
{},
{
Max: NewFloatPoint(20),
Formatter: "{value} C",
},
},
SeriesList: []Series{
{
YAxisIndex: 1,
Data: []SeriesData{
{
Value: 1,
},
{
Value: 2,
},
},
},
},
}
},
axisIndex: 1,
result: "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"400\" height=\"300\">\\n<path d=\"M 337 10\nL 337 290\" style=\"stroke-width:1;stroke:none;fill:none\"/><text x=\"345\" y=\"294\" style=\"stroke-width:0;stroke:none;fill:rgba(110,112,121,1.0);font-size:12.8px;font-family:'Roboto Medium',sans-serif\">0 C</text><text x=\"345\" y=\"248\" style=\"stroke-width:0;stroke:none;fill:rgba(110,112,121,1.0);font-size:12.8px;font-family:'Roboto Medium',sans-serif\">3.33 C</text><text x=\"345\" y=\"202\" style=\"stroke-width:0;stroke:none;fill:rgba(110,112,121,1.0);font-size:12.8px;font-family:'Roboto Medium',sans-serif\">6.66 C</text><text x=\"345\" y=\"155\" style=\"stroke-width:0;stroke:none;fill:rgba(110,112,121,1.0);font-size:12.8px;font-family:'Roboto Medium',sans-serif\">10 C</text><text x=\"345\" y=\"108\" style=\"stroke-width:0;stroke:none;fill:rgba(110,112,121,1.0);font-size:12.8px;font-family:'Roboto Medium',sans-serif\">13.33 C</text><text x=\"345\" y=\"61\" style=\"stroke-width:0;stroke:none;fill:rgba(110,112,121,1.0);font-size:12.8px;font-family:'Roboto Medium',sans-serif\">16.66 C</text><text x=\"345\" y=\"14\" style=\"stroke-width:0;stroke:none;fill:rgba(110,112,121,1.0);font-size:12.8px;font-family:'Roboto Medium',sans-serif\">20 C</text></svg>",
},
}
for _, tt := range tests {
d := tt.newDraw()
r, err := drawYAxis(d, tt.newOption(), 0, tt.xAxisHeight, chart.NewBox(10, 10, 10, 10))
r, err := drawYAxis(d, tt.newOption(), tt.axisIndex, tt.xAxisHeight, chart.NewBox(10, 10, 10, 10))
assert.Nil(err)
assert.Equal(&Range{
divideCount: 6,