diff --git a/axis.go b/axis.go index 14648cf..29cc3cc 100644 --- a/axis.go +++ b/axis.go @@ -78,14 +78,17 @@ func NewAxis(d *Draw, data AxisDataList, style AxisOption) *axis { } +// GetLabelMargin returns the label margin value func (as *AxisOption) GetLabelMargin() int { return getDefaultInt(as.LabelMargin, 8) } +// GetTickLength returns the tick length value func (as *AxisOption) GetTickLength() int { return getDefaultInt(as.TickLength, 5) } +// Style returns the style of axis func (as *AxisOption) Style(f *truetype.Font) chart.Style { s := chart.Style{ ClassName: as.ClassName, @@ -109,6 +112,7 @@ type AxisData struct { } type AxisDataList []AxisData +// TextList returns the text list of axis data func (l AxisDataList) TextList() []string { textList := make([]string, len(l)) for index, item := range l { @@ -125,6 +129,7 @@ type axisRenderOption struct { modValue int } +// NewAxisDataListFromStringList creates a new axis data list from string list func NewAxisDataListFromStringList(textList []string) AxisDataList { list := make(AxisDataList, len(textList)) for index, text := range textList { diff --git a/bar_chart.go b/bar_chart.go index d9917f1..7a5805b 100644 --- a/bar_chart.go +++ b/bar_chart.go @@ -37,7 +37,7 @@ func barChartRender(opt ChartOption, result *basicRenderResult) (*Draw, error) { if err != nil { return nil, err } - yRange := result.yRange + // yRange := result.yRange xRange := result.xRange x0, x1 := xRange.GetRange(0) width := int(x1 - x0) @@ -50,7 +50,7 @@ func barChartRender(opt ChartOption, result *basicRenderResult) (*Draw, error) { // 总的宽度-两个margin-(总数-1)的barMargin barWidth := (width - 2*margin - barMargin*(seriesCount-1)) / len(opt.SeriesList) - barMaxHeight := yRange.Size + barMaxHeight := result.getYRange(0).Size theme := NewTheme(opt.Theme) seriesNames := opt.Legend.Data @@ -58,6 +58,9 @@ func barChartRender(opt ChartOption, result *basicRenderResult) (*Draw, error) { r := d.Render for i, series := range opt.SeriesList { + yRange := result.getYRange(series.YAxisIndex) + points := make([]Point, len(series.Data)) + seriesColor := theme.GetSeriesColor(i) for j, item := range series.Data { x0, _ := xRange.GetRange(j) x := int(x0) @@ -67,26 +70,32 @@ func barChartRender(opt ChartOption, result *basicRenderResult) (*Draw, error) { } h := int(yRange.getHeight(item.Value)) - fillColor := theme.GetSeriesColor(i) + fillColor := seriesColor if !item.Style.FillColor.IsZero() { fillColor = item.Style.FillColor } - + top := barMaxHeight - h d.Bar(chart.Box{ - Top: barMaxHeight - h, + Top: top, Left: x, Right: x + barWidth, Bottom: barMaxHeight - 1, }, BarStyle{ FillColor: fillColor, }) + // 用于生成marker point + points[j] = Point{ + // 居中的位置 + X: x + barWidth>>1, + Y: top, + } if !series.Label.Show { continue } text := NewValueLabelFormater(seriesNames, series.Label.Formatter)(i, item.Value, -1) labelStyle := chart.Style{ FontColor: theme.GetTextColor(), - FontSize: 10, + FontSize: labelFontSize, Font: opt.Font, } if !series.Label.Color.IsZero() { @@ -96,6 +105,12 @@ 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{ + FillColor: seriesColor, + Font: opt.Font, + Points: points, + Series: &series, + }) } return result.d, nil diff --git a/chart.go b/chart.go index 7c511de..dbc4db4 100644 --- a/chart.go +++ b/chart.go @@ -42,6 +42,8 @@ type Point struct { Y int } +const labelFontSize = 10 + type ChartOption struct { Type string Font *truetype.Font @@ -49,7 +51,7 @@ type ChartOption struct { Title TitleOption Legend LegendOption XAxis XAxisOption - YAxis YAxisOption + YAxisList []YAxisOption Width int Height int Parent *Draw @@ -61,6 +63,17 @@ type ChartOption struct { func (o *ChartOption) FillDefault(theme string) { t := NewTheme(theme) + // 如果为空,初始化 + yAxisCount := 1 + for _, series := range o.SeriesList { + if series.YAxisIndex >= yAxisCount { + yAxisCount++ + } + } + yAxisList := make([]YAxisOption, yAxisCount) + copy(yAxisList, o.YAxisList) + o.YAxisList = yAxisList + if o.Font == nil { o.Font, _ = chart.GetDefaultFont() } @@ -136,9 +149,13 @@ func (o *ChartOption) getHeight() int { return o.Height } -func (o *ChartOption) getYRange(axisIndex int) Range { +func (o *ChartOption) newYRange(axisIndex int) Range { min := math.MaxFloat64 max := -math.MaxFloat64 + if axisIndex >= len(o.YAxisList) { + axisIndex = 0 + } + yAxis := o.YAxisList[axisIndex] for _, series := range o.SeriesList { if series.YAxisIndex != axisIndex { @@ -155,21 +172,21 @@ func (o *ChartOption) getYRange(axisIndex int) Range { } min = min * 0.9 max = max * 1.1 - if o.YAxis.Min != nil { - min = *o.YAxis.Min + if yAxis.Min != nil { + min = *yAxis.Min } - if o.YAxis.Max != nil { - max = *o.YAxis.Max + if yAxis.Max != nil { + max = *yAxis.Max } divideCount := 6 // y轴分设置默认划分为6块 r := NewRange(min, max, divideCount) // 由于NewRange会重新计算min max - if o.YAxis.Min != nil { + if yAxis.Min != nil { r.Min = min } - if o.YAxis.Max != nil { + if yAxis.Max != nil { r.Max = max } @@ -177,10 +194,17 @@ func (o *ChartOption) getYRange(axisIndex int) Range { } type basicRenderResult struct { - xRange *Range - yRange *Range - d *Draw - titleBox chart.Box + xRange *Range + yRangeList []*Range + d *Draw + titleBox chart.Box +} + +func (r *basicRenderResult) getYRange(index int) *Range { + if index >= len(r.yRangeList) { + index = 0 + } + return r.yRangeList[index] } func Render(opt ChartOption) (*Draw, error) { @@ -206,7 +230,9 @@ func Render(opt ChartOption) (*Draw, error) { // pie不需要axis if isPieChart { opt.XAxis.Hidden = true - opt.YAxis.Hidden = true + for index := range opt.YAxisList { + opt.YAxisList[index].Hidden = true + } } result, err := chartBasicRender(&opt) if err != nil { @@ -284,6 +310,9 @@ func chartBasicRender(opt *ChartOption) (*basicRenderResult, error) { } opt.FillDefault(opt.Theme) + if len(opt.YAxisList) > 2 { + return nil, errors.New("y axis should not be gt 2") + } if opt.Parent == nil { d.setBackground(opt.getWidth(), opt.getHeight(), opt.BackgroundColor) } @@ -299,26 +328,30 @@ func chartBasicRender(opt *ChartOption) (*basicRenderResult, error) { if !opt.XAxis.Hidden { // xAxis - xAxisHeight, xRange, err = drawXAxis(d, &opt.XAxis) + xAxisHeight, xRange, err = drawXAxis(d, &opt.XAxis, len(opt.YAxisList)) if err != nil { return nil, err } } - // 暂时仅支持单一yaxis - var yRange *Range - if !opt.YAxis.Hidden { - yRange, err = drawYAxis(d, opt, xAxisHeight, chart.Box{ - Top: titleBox.Height(), - }) - if err != nil { - return nil, err + yRangeList := make([]*Range, len(opt.YAxisList)) + + for index, yAxis := range opt.YAxisList { + var yRange *Range + if !yAxis.Hidden { + yRange, err = drawYAxis(d, opt, index, xAxisHeight, chart.Box{ + Top: titleBox.Height(), + }) + if err != nil { + return nil, err + } + yRangeList[index] = yRange } } return &basicRenderResult{ - xRange: xRange, - yRange: yRange, - d: d, - titleBox: titleBox, + xRange: xRange, + yRangeList: yRangeList, + d: d, + titleBox: titleBox, }, nil } diff --git a/draw.go b/draw.go index c7f0849..5c65d87 100644 --- a/draw.go +++ b/draw.go @@ -173,7 +173,60 @@ 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.Fill() + d.Render.Stroke() +} + +func (d *Draw) arrowLeft(x, y, width, height int) { + d.arrow(x, y, width, height, PositionLeft) +} + +func (d *Draw) arrowRight(x, y, width, height int) { + d.arrow(x, y, width, height, PositionRight) +} + +func (d *Draw) arrowTop(x, y, width, height int) { + d.arrow(x, y, width, height, PositionTop) +} +func (d *Draw) arrowBottom(x, y, width, height int) { + d.arrow(x, y, width, height, PositionBottom) +} + +func (d *Draw) arrow(x, y, width, height int, direction string) { + halfWidth := width >> 1 + halfHeight := height >> 1 + if direction == PositionTop || direction == PositionBottom { + x0 := x - halfWidth + x1 := x0 + width + dy := -height / 3 + y0 := y + y1 := y0 - height + if direction == PositionBottom { + y0 = y - height + y1 = y + dy = 2 * dy + } + d.moveTo(x0, y0) + d.lineTo(x0+halfWidth, y1) + d.lineTo(x1, y0) + d.lineTo(x0+halfWidth, y+dy) + d.lineTo(x0, y0) + } else { + x0 := x + width + x1 := x0 - width + y0 := y - halfHeight + dx := -width / 3 + if direction == PositionRight { + x0 = x - width + dx = -dx + x1 = x0 + width + } + d.moveTo(x0, y0) + d.lineTo(x1, y0+halfHeight) + d.lineTo(x0, y0+height) + d.lineTo(x0+dx, y0+halfHeight) + d.lineTo(x0, y0) + } + d.Render.Stroke() } func (d *Draw) circle(radius float64, x, y int) { diff --git a/draw_test.go b/draw_test.go index dcba961..efda7eb 100644 --- a/draw_test.go +++ b/draw_test.go @@ -239,6 +239,7 @@ func TestDraw(t *testing.T) { }, result: "\\n", }, + // pin { fn: func(d *Draw) { chart.Style{ @@ -260,6 +261,94 @@ func TestDraw(t *testing.T) { }, result: "\\n", }, + // arrow left + { + 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, + }, + }.WriteToRenderer(d.Render) + d.arrowLeft(30, 30, 16, 10) + }, + result: "\\n", + }, + // arrow right + { + 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, + }, + }.WriteToRenderer(d.Render) + d.arrowRight(30, 30, 16, 10) + }, + result: "\\n", + }, + // arrow top + { + 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, + }, + }.WriteToRenderer(d.Render) + d.arrowTop(30, 30, 10, 16) + }, + result: "\\n", + }, + // arrow bottom + { + 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, + }, + }.WriteToRenderer(d.Render) + d.arrowBottom(30, 30, 10, 16) + }, + result: "\\n", + }, } for _, tt := range tests { d, err := NewDraw(DrawOption{ diff --git a/line_chart.go b/line_chart.go index 91e1a6d..39d8b4d 100644 --- a/line_chart.go +++ b/line_chart.go @@ -23,8 +23,6 @@ package charts import ( - "math" - "github.com/wcharczuk/go-chart/v2" "github.com/wcharczuk/go-chart/v2/drawing" ) @@ -45,36 +43,25 @@ func lineChartRender(opt ChartOption, result *basicRenderResult) (*Draw, error) seriesNames := opt.Legend.Data r := d.Render - yRange := result.yRange xRange := result.xRange for i, series := range opt.SeriesList { - points := make([]Point, 0) - minIndex := -1 - maxIndex := -1 - minValue := math.MaxFloat64 - maxValue := -math.MaxFloat64 + yRange := result.getYRange(series.YAxisIndex) + points := make([]Point, len(series.Data)) + for j, item := range series.Data { - if item.Value < minValue { - minIndex = j - minValue = item.Value - } - if item.Value > maxValue { - maxIndex = j - maxValue = item.Value - } y := yRange.getRestHeight(item.Value) x := xRange.getWidth(float64(j)) - points = append(points, Point{ + points[j] = Point{ Y: y, X: x, - }) + } if !series.Label.Show { continue } text := NewValueLabelFormater(seriesNames, series.Label.Formatter)(i, item.Value, -1) labelStyle := chart.Style{ FontColor: theme.GetTextColor(), - FontSize: 10, + FontSize: labelFontSize, Font: opt.Font, } if !series.Label.Color.IsZero() { @@ -101,33 +88,12 @@ func lineChartRender(opt ChartOption, result *basicRenderResult) (*Draw, error) DotFillColor: dotFillColor, }) // draw mark point - symbolSize := 30 - if series.MarkPoint.SymbolSize > 0 { - symbolSize = series.MarkPoint.SymbolSize - } - for _, markPointData := range series.MarkPoint.Data { - p := points[minIndex] - value := minValue - switch markPointData.Type { - case SeriesMarkPointDataTypeMax: - p = points[maxIndex] - value = maxValue - } - chart.Style{ - FillColor: seriesColor, - }.WriteToRenderer(r) - d.pin(p.X, p.Y-symbolSize>>1, symbolSize) - - chart.Style{ - FontColor: NewTheme(ThemeDark).GetTextColor(), - FontSize: 10, - StrokeWidth: 1, - Font: opt.Font, - }.WriteTextOptionsToRenderer(d.Render) - text := commafWithDigits(value) - textBox := r.MeasureText(text) - d.text(text, p.X-textBox.Width()>>1, p.Y-symbolSize>>1-2) - } + markPointRender(d, markPointRenderOption{ + FillColor: seriesColor, + Font: opt.Font, + Points: points, + Series: &series, + }) } return result.d, nil diff --git a/mark_point.go b/mark_point.go new file mode 100644 index 0000000..f1a429f --- /dev/null +++ b/mark_point.go @@ -0,0 +1,75 @@ +// 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" +) + +type markPointRenderOption struct { + FillColor drawing.Color + Font *truetype.Font + Series *Series + Points []Point +} + +func markPointRender(d *Draw, opt markPointRenderOption) { + s := opt.Series + if len(s.MarkPoint.Data) == 0 { + return + } + points := opt.Points + summary := s.Summary() + symbolSize := s.MarkPoint.SymbolSize + if symbolSize == 0 { + symbolSize = 30 + } + r := d.Render + // 设置填充样式 + chart.Style{ + FillColor: opt.FillColor, + }.WriteToRenderer(r) + // 设置文本样式 + chart.Style{ + FontColor: NewTheme(ThemeDark).GetTextColor(), + FontSize: 10, + StrokeWidth: 1, + Font: opt.Font, + }.WriteTextOptionsToRenderer(r) + for _, markPointData := range s.MarkPoint.Data { + p := points[summary.MinIndex] + value := summary.MinValue + switch markPointData.Type { + case SeriesMarkPointDataTypeMax: + p = points[summary.MaxIndex] + value = summary.MaxValue + } + + d.pin(p.X, p.Y-symbolSize>>1, symbolSize) + text := commafWithDigits(value) + textBox := r.MeasureText(text) + d.text(text, p.X-textBox.Width()>>1, p.Y-symbolSize>>1-2) + } +} diff --git a/pie_chart.go b/pie_chart.go index d2cd029..84751f9 100644 --- a/pie_chart.go +++ b/pie_chart.go @@ -136,7 +136,7 @@ func pieChartRender(opt ChartOption, result *basicRenderResult) (*Draw, error) { r.Stroke() textStyle := chart.Style{ FontColor: theme.GetTextColor(), - FontSize: 10, + FontSize: labelFontSize, Font: opt.Font, } if !series.Label.Color.IsZero() { diff --git a/range.go b/range.go index 0d1b459..308dba8 100644 --- a/range.go +++ b/range.go @@ -40,9 +40,15 @@ func NewRange(min, max float64, divideCount int) Range { // 最小单位计算 unit := 2 if r > 10 { + unit = 4 + } + if r > 30 { unit = 5 } if r > 100 { + unit = 10 + } + if r > 200 { unit = 20 } unit = int((r/float64(divideCount))/float64(unit))*unit + unit diff --git a/range_test.go b/range_test.go index b10002f..06c25fd 100644 --- a/range_test.go +++ b/range_test.go @@ -37,12 +37,16 @@ func TestRange(t *testing.T) { r = NewRange(0, 12, 6) assert.Equal(0.0, r.Min) - assert.Equal(30.0, r.Max) + assert.Equal(24.0, r.Max) r = NewRange(-13, 18, 6) assert.Equal(-20.0, r.Min) assert.Equal(40.0, r.Max) + r = NewRange(0, 150, 6) + assert.Equal(0.0, r.Min) + assert.Equal(180.0, r.Max) + r = NewRange(0, 400, 6) assert.Equal(0.0, r.Min) assert.Equal(480.0, r.Max) diff --git a/series.go b/series.go index 8b5161d..b37e13d 100644 --- a/series.go +++ b/series.go @@ -23,6 +23,7 @@ package charts import ( + "math" "strings" "github.com/dustin/go-humanize" @@ -86,6 +87,40 @@ type Series struct { MarkPoint SeriesMarkPoint } +type seriesSummary struct { + MaxIndex int + MaxValue float64 + MinIndex int + MinValue float64 + AverageValue float64 +} + +func (s *Series) Summary() seriesSummary { + minIndex := -1 + maxIndex := -1 + minValue := math.MaxFloat64 + maxValue := -math.MaxFloat64 + sum := float64(0) + for j, item := range s.Data { + if item.Value < minValue { + minIndex = j + minValue = item.Value + } + if item.Value > maxValue { + maxIndex = j + maxValue = item.Value + } + sum += item.Value + } + return seriesSummary{ + MaxIndex: maxIndex, + MaxValue: maxValue, + MinIndex: minIndex, + MinValue: minValue, + AverageValue: sum / float64(len(s.Data)), + } +} + type LabelFormatter func(index int, value float64, percent float64) string func NewPieLabelFormatter(seriesNames []string, layout string) LabelFormatter { diff --git a/util.go b/util.go index 5c1415d..3064668 100644 --- a/util.go +++ b/util.go @@ -106,7 +106,7 @@ func isFalse(flag *bool) bool { return false } -func toFloatPoint(f float64) *float64 { +func NewFloatPoint(f float64) *float64 { v := f return &v } @@ -114,11 +114,11 @@ func commafWithDigits(value float64) string { decimals := 2 m := float64(1000 * 1000) if value >= m { - return humanize.CommafWithDigits(value/m, decimals) + " M" + return humanize.CommafWithDigits(value/m, decimals) + "M" } k := float64(1000) if value >= k { - return humanize.CommafWithDigits(value/k, decimals) + " K" + return humanize.CommafWithDigits(value/k, decimals) + "k" } return humanize.CommafWithDigits(value, decimals) } diff --git a/xaxis.go b/xaxis.go index 60c7c23..5c21c14 100644 --- a/xaxis.go +++ b/xaxis.go @@ -22,7 +22,9 @@ package charts -import "github.com/wcharczuk/go-chart/v2" +import ( + "github.com/wcharczuk/go-chart/v2" +) type XAxisOption struct { // The boundary gap on both sides of a coordinate axis. @@ -39,16 +41,19 @@ type XAxisOption struct { } // drawXAxis draws x axis, and returns the height, range of if. -func drawXAxis(p *Draw, opt *XAxisOption) (int, *Range, error) { +func drawXAxis(p *Draw, opt *XAxisOption, yAxisCount int) (int, *Range, error) { if opt.Hidden { return 0, nil, nil } + left := YAxisWidth + right := (yAxisCount - 1) * YAxisWidth dXAxis, err := NewDraw( DrawOption{ Parent: p, }, PaddingOption(chart.Box{ - Left: YAxisWidth, + Left: left, + Right: right, }), ) if err != nil { diff --git a/xaxis_test.go b/xaxis_test.go index bce3863..44e8a3f 100644 --- a/xaxis_test.go +++ b/xaxis_test.go @@ -81,7 +81,7 @@ func TestDrawXAxis(t *testing.T) { for _, tt := range tests { d := tt.newDraw() - height, _, err := drawXAxis(d, tt.newOption()) + height, _, err := drawXAxis(d, tt.newOption(), 1) assert.Nil(err) assert.Equal(25, height) data, err := d.Bytes() diff --git a/yaxis.go b/yaxis.go index 1742e99..b978d08 100644 --- a/yaxis.go +++ b/yaxis.go @@ -41,11 +41,11 @@ type YAxisOption struct { const YAxisWidth = 40 -func drawYAxis(p *Draw, opt *ChartOption, xAxisHeight int, padding chart.Box) (*Range, error) { +func drawYAxis(p *Draw, opt *ChartOption, axisIndex, xAxisHeight int, padding chart.Box) (*Range, error) { theme := NewTheme(opt.Theme) - yRange := opt.getYRange(0) + yRange := opt.newYRange(axisIndex) values := yRange.Values() - formatter := opt.YAxis.Formatter + formatter := opt.YAxisList[axisIndex].Formatter if len(formatter) != 0 { for index, text := range values { values[index] = strings.ReplaceAll(formatter, "{value}", text) @@ -64,12 +64,21 @@ func drawYAxis(p *Draw, opt *ChartOption, xAxisHeight int, padding chart.Box) (* } width := NewAxis(p, data, style).measureAxis() - padding.Left += (YAxisWidth - width) + yAxisCount := len(opt.YAxisList) + boxWidth := p.Box.Width() + if axisIndex > 0 { + style.SplitLineShow = false + style.Position = PositionRight + padding.Right += (axisIndex - 1) * YAxisWidth + } else { + boxWidth = p.Box.Width() - (yAxisCount-1)*YAxisWidth + padding.Left += (YAxisWidth - width) + } dYAxis, err := NewDraw( DrawOption{ Parent: p, - Width: p.Box.Width(), + Width: boxWidth, // 减去x轴的高 Height: p.Box.Height() - xAxisHeight, }, diff --git a/yaxis_test.go b/yaxis_test.go index 634ff59..5c66caa 100644 --- a/yaxis_test.go +++ b/yaxis_test.go @@ -49,8 +49,10 @@ func TestDrawYAxis(t *testing.T) { newDraw: newDraw, newOption: func() *ChartOption { return &ChartOption{ - YAxis: YAxisOption{ - Max: toFloatPoint(20), + YAxisList: []YAxisOption{ + { + Max: NewFloatPoint(20), + }, }, SeriesList: []Series{ { @@ -72,7 +74,7 @@ func TestDrawYAxis(t *testing.T) { for _, tt := range tests { d := tt.newDraw() - r, err := drawYAxis(d, tt.newOption(), tt.xAxisHeight, chart.NewBox(10, 10, 10, 10)) + r, err := drawYAxis(d, tt.newOption(), 0, tt.xAxisHeight, chart.NewBox(10, 10, 10, 10)) assert.Nil(err) assert.Equal(&Range{ divideCount: 6,