feat: support customize table cell style

This commit is contained in:
vicanso 2022-06-28 20:21:06 +08:00
parent 0eecb6c5b7
commit d53fa1a329
2 changed files with 142 additions and 9 deletions

View file

@ -4,18 +4,20 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strconv"
"github.com/vicanso/go-charts/v2" "github.com/vicanso/go-charts/v2"
"github.com/wcharczuk/go-chart/v2/drawing"
) )
func writeFile(buf []byte) error { func writeFile(buf []byte, filename string) error {
tmpPath := "./tmp" tmpPath := "./tmp"
err := os.MkdirAll(tmpPath, 0700) err := os.MkdirAll(tmpPath, 0700)
if err != nil { if err != nil {
return err return err
} }
file := filepath.Join(tmpPath, "table.png") file := filepath.Join(tmpPath, filename)
err = ioutil.WriteFile(file, buf, 0600) err = ioutil.WriteFile(file, buf, 0600)
if err != nil { if err != nil {
return err return err
@ -77,7 +79,54 @@ func main() {
if err != nil { if err != nil {
panic(err) panic(err)
} }
err = writeFile(buf) err = writeFile(buf, "table.png")
if err != nil {
panic(err)
}
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
},
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 row == 3 && column == 4 {
return &charts.Style{
FillColor: drawing.ColorRed.WithAlpha(100),
}
}
return nil
},
})
if err != nil {
panic(err)
}
buf, err = p.Bytes()
if err != nil {
panic(err)
}
err = writeFile(buf, "table-color.png")
if err != nil { if err != nil {
panic(err) panic(err)
} }

View file

@ -46,6 +46,17 @@ func NewTableChart(p *Painter, opt TableChartOption) *tableChart {
} }
} }
type TableCell struct {
// Text the text of table cell
Text string
// Style the current style of table cell
Style Style
// Row the row index of table cell
Row int
// Column the column index of table cell
Column int
}
type TableChartOption struct { type TableChartOption struct {
// The output type // The output type
Type string Type string
@ -76,6 +87,10 @@ type TableChartOption struct {
RowBackgroundColors []Color RowBackgroundColors []Color
// The background color // The background color
BackgroundColor Color BackgroundColor Color
// CellTextStyle customize text style of table cell
CellTextStyle func(TableCell) *Style
// CellStyle customize drawing style of table cell
CellStyle func(TableCell) *Style
} }
type TableSetting struct { type TableSetting struct {
@ -180,6 +195,7 @@ type renderInfo struct {
Height int Height int
HeaderHeight int HeaderHeight int
RowHeights []int RowHeights []int
ColumnWidths []int
} }
func (t *tableChart) render() (*renderInfo, error) { func (t *tableChart) render() (*renderInfo, error) {
@ -227,6 +243,15 @@ func (t *tableChart) render() (*renderInfo, error) {
sum := sumInt(spans) sum := sumInt(spans)
values := autoDivideSpans(p.Width(), sum, spans) values := autoDivideSpans(p.Width(), sum, spans)
columnWidths := make([]int, 0)
for index, v := range values {
if index == len(values)-1 {
break
}
columnWidths = append(columnWidths, values[index+1]-v)
}
info.ColumnWidths = columnWidths
height := 0 height := 0
textStyle := Style{ textStyle := Style{
FontSize: fontSize, FontSize: fontSize,
@ -234,25 +259,48 @@ func (t *tableChart) render() (*renderInfo, error) {
FillColor: headerFontColor, FillColor: headerFontColor,
Font: font, Font: font,
} }
p.SetStyle(textStyle)
headerHeight := 0 headerHeight := 0
padding := opt.Padding padding := opt.Padding
if padding.IsZero() { if padding.IsZero() {
padding = tableDefaultSetting.Padding padding = tableDefaultSetting.Padding
} }
getCellTextStyle := opt.CellTextStyle
if getCellTextStyle == nil {
getCellTextStyle = func(_ TableCell) *Style {
return nil
}
}
renderTableCells := func(textList []string, currentHeight int, cellPadding Box) int { // 表格单元的处理
renderTableCells := func(
currentStyle Style,
rowIndex int,
textList []string,
currentHeight int,
cellPadding Box,
) int {
cellMaxHeight := 0 cellMaxHeight := 0
paddingHeight := cellPadding.Top + cellPadding.Bottom paddingHeight := cellPadding.Top + cellPadding.Bottom
paddingWidth := cellPadding.Left + cellPadding.Right paddingWidth := cellPadding.Left + cellPadding.Right
for index, text := range textList { for index, text := range textList {
cellStyle := getCellTextStyle(TableCell{
Text: text,
Row: rowIndex,
Column: index,
Style: currentStyle,
})
if cellStyle == nil {
cellStyle = &currentStyle
}
p.SetStyle(*cellStyle)
x := values[index] x := values[index]
y := currentHeight + cellPadding.Top y := currentHeight + cellPadding.Top
width := values[index+1] - x width := values[index+1] - x
x += cellPadding.Left x += cellPadding.Left
width -= paddingWidth width -= paddingWidth
box := p.TextFit(text, x, y+int(fontSize), width) box := p.TextFit(text, x, y+int(fontSize), width)
// 计算最高的高度
if box.Height()+paddingHeight > cellMaxHeight { if box.Height()+paddingHeight > cellMaxHeight {
cellMaxHeight = box.Height() + paddingHeight cellMaxHeight = box.Height() + paddingHeight
} }
@ -260,15 +308,16 @@ func (t *tableChart) render() (*renderInfo, error) {
return cellMaxHeight return cellMaxHeight
} }
headerHeight = renderTableCells(opt.Header, height, padding) // 表头的处理
headerHeight = renderTableCells(textStyle, 0, opt.Header, height, padding)
height += headerHeight height += headerHeight
info.HeaderHeight = headerHeight info.HeaderHeight = headerHeight
// 表格内容的处理
textStyle.FontColor = fontColor textStyle.FontColor = fontColor
textStyle.FillColor = fontColor textStyle.FillColor = fontColor
p.SetStyle(textStyle) for index, textList := range opt.Data {
for _, textList := range opt.Data { cellHeight := renderTableCells(textStyle, index+1, textList, height, padding)
cellHeight := renderTableCells(textList, height, padding)
info.RowHeights = append(info.RowHeights, cellHeight) info.RowHeights = append(info.RowHeights, cellHeight)
height += cellHeight height += cellHeight
} }
@ -304,6 +353,41 @@ func (t *tableChart) renderWithInfo(info *renderInfo) (Box, error) {
child.SetBackground(p.Width(), h, color, true) child.SetBackground(p.Width(), h, color, true)
currentHeight += h currentHeight += h
} }
// 根据是否有设置表格样式调整背景色
getCellStyle := opt.CellStyle
if getCellStyle != nil {
arr := [][]string{
opt.Header,
}
arr = append(arr, opt.Data...)
top := 0
heights := []int{
info.HeaderHeight,
}
heights = append(heights, info.RowHeights...)
// 循环所有表格单元,生成背景色
for i, textList := range arr {
left := 0
for j, v := range textList {
style := getCellStyle(TableCell{
Text: v,
Row: i,
Column: j,
})
if style != nil && !style.FillColor.IsZero() {
child := p.Child(PainterPaddingOption(Box{
Top: top,
Left: left,
}))
w := info.ColumnWidths[j]
h := heights[i]
child.SetBackground(w, h, style.FillColor, true)
}
left += info.ColumnWidths[j]
}
top += heights[i]
}
}
_, err := t.render() _, err := t.render()
if err != nil { if err != nil {
return BoxZero, err return BoxZero, err