diff --git a/assets/go-table.png b/assets/go-table.png index b05a3d0..88ec49c 100644 Binary files a/assets/go-table.png and b/assets/go-table.png differ diff --git a/examples/table/main.go b/examples/table/main.go index f332851..2701ec1 100644 --- a/examples/table/main.go +++ b/examples/table/main.go @@ -5,6 +5,7 @@ import ( "os" "path/filepath" "strconv" + "strings" "github.com/vicanso/go-charts/v2" "github.com/wcharczuk/go-chart/v2/drawing" @@ -84,38 +85,83 @@ func main() { panic(err) } + bgColor := charts.Color{ + R: 16, + G: 22, + B: 30, + A: 255, + } p, err = charts.TableOptionRender(charts.TableChartOption{ - Header: header, - Data: data, - CellTextStyle: func(tc charts.TableCell) *charts.Style { - row := tc.Row - column := tc.Column - style := tc.Style - if column == 1 && row != 0 { - age, _ := strconv.Atoi(tc.Text) - if age < 40 { - style.FontColor = drawing.ColorGreen - } else { - style.FontColor = drawing.ColorRed - } - return &style - } - return nil + Header: []string{ + "Name", + "Price", + "Change", + }, + BackgroundColor: bgColor, + HeaderBackgroundColor: bgColor, + RowBackgroundColors: []charts.Color{ + bgColor, + }, + HeaderFontColor: drawing.ColorWhite, + FontColor: drawing.ColorWhite, + Padding: charts.Box{ + Top: 15, + Right: 10, + Bottom: 15, + Left: 10, + }, + Data: [][]string{ + { + "Datadog Inc", + "97.32", + "-7.49%", + }, + { + "Hashicorp Inc", + "28.66", + "-9.25%", + }, + { + "Gitlab Inc", + "51.63", + "+4.32%", + }, + }, + TextAligns: []string{ + "", + charts.AlignRight, + charts.AlignRight, }, CellStyle: func(tc charts.TableCell) *charts.Style { - row := tc.Row column := tc.Column - if row == 2 && column == 1 { - return &charts.Style{ - FillColor: drawing.ColorBlue, + if column != 2 { + return nil + } + value, _ := strconv.ParseFloat(strings.Replace(tc.Text, "%", "", 1), 64) + if value == 0 { + return nil + } + style := charts.Style{ + Padding: charts.Box{ + Bottom: 5, + }, + } + if value > 0 { + style.FillColor = charts.Color{ + R: 179, + G: 53, + B: 20, + A: 255, + } + } else if value < 0 { + style.FillColor = charts.Color{ + R: 33, + G: 124, + B: 50, + A: 255, } } - if row == 3 && column == 4 { - return &charts.Style{ - FillColor: drawing.ColorRed.WithAlpha(100), - } - } - return nil + return &style }, }) if err != nil { diff --git a/painter.go b/painter.go index 06973b6..62a4378 100644 --- a/painter.go +++ b/painter.go @@ -545,7 +545,7 @@ func (p *Painter) Text(body string, x, y int) *Painter { return p } -func (p *Painter) TextFit(body string, x, y, width int) chart.Box { +func (p *Painter) TextFit(body string, x, y, width int, textAligns ...string) chart.Box { style := p.style textWarp := style.TextWrap style.TextWrap = chart.TextWrapWord @@ -554,14 +554,24 @@ func (p *Painter) TextFit(body string, x, y, width int) chart.Box { p.SetTextStyle(style) var output chart.Box + textAlign := "" + if len(textAligns) != 0 { + textAlign = textAligns[0] + } for index, line := range lines { if line == "" { continue } x0 := x y0 := y + output.Height() - p.Text(line, x0, y0) lineBox := r.MeasureText(line) + switch textAlign { + case AlignRight: + x0 += width - lineBox.Width() + case AlignCenter: + x0 += (width - lineBox.Width()) >> 1 + } + p.Text(line, x0, y0) output.Right = chart.MaxInt(lineBox.Right, output.Right) output.Bottom += lineBox.Height() if index < len(lines)-1 { diff --git a/table.go b/table.go index d1af5f9..86ef569 100644 --- a/table.go +++ b/table.go @@ -70,8 +70,10 @@ type TableChartOption struct { Header []string // The data of table Data [][]string - // The span of table column + // The span list of table column Spans []int + // The text align list of table cell + TextAligns []string // The font size of table FontSize float64 // The font family, which should be installed first @@ -271,6 +273,13 @@ func (t *tableChart) render() (*renderInfo, error) { return nil } } + // textAligns := opt.TextAligns + getTextAlign := func(index int) string { + if len(opt.TextAligns) <= index { + return "" + } + return opt.TextAligns[index] + } // 表格单元的处理 renderTableCells := func( @@ -299,7 +308,7 @@ func (t *tableChart) render() (*renderInfo, error) { width := values[index+1] - x x += cellPadding.Left width -= paddingWidth - box := p.TextFit(text, x, y+int(fontSize), width) + box := p.TextFit(text, x, y+int(fontSize), width, getTextAlign(index)) // 计算最高的高度 if box.Height()+paddingHeight > cellMaxHeight { cellMaxHeight = box.Height() + paddingHeight @@ -342,7 +351,7 @@ func (t *tableChart) renderWithInfo(info *renderInfo) (Box, error) { p.SetBackground(info.Width, info.HeaderHeight, headerBGColor, true) currentHeight := info.HeaderHeight rowColors := opt.RowBackgroundColors - if len(rowColors) == 0 { + if rowColors == nil { rowColors = tableDefaultSetting.RowColors } for index, h := range info.RowHeights { @@ -375,12 +384,13 @@ func (t *tableChart) renderWithInfo(info *renderInfo) (Box, error) { Column: j, }) if style != nil && !style.FillColor.IsZero() { + padding := style.Padding child := p.Child(PainterPaddingOption(Box{ - Top: top, - Left: left, + Top: top + padding.Top, + Left: left + padding.Left, })) - w := info.ColumnWidths[j] - h := heights[i] + w := info.ColumnWidths[j] - padding.Left - padding.Top + h := heights[i] - padding.Top - padding.Bottom child.SetBackground(w, h, style.FillColor, true) } left += info.ColumnWidths[j]