* Add stacked bar chart value labels (#60)
* Add horizontal render option to stacked bar chart (#39)
* Pulling 100% inside the canvasBox to remain visible.
* Use correct margins for YAxis.TextHorizontalAlign: chart.TextHorizontalAlignRight
* Fixed Show to Hidden due to 5f42a580a9
This commit is contained in:
parent
3a7bc55431
commit
962b9abdec
7 changed files with 688 additions and 8 deletions
222
_examples/horizontal_stacked_bar/main.go
Normal file
222
_examples/horizontal_stacked_bar/main.go
Normal file
|
@ -0,0 +1,222 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/wcharczuk/go-chart"
|
||||
"github.com/wcharczuk/go-chart/drawing"
|
||||
)
|
||||
|
||||
func main() {
|
||||
chart.DefaultBackgroundColor = chart.ColorTransparent
|
||||
chart.DefaultCanvasColor = chart.ColorTransparent
|
||||
|
||||
barWidth := 80
|
||||
|
||||
var (
|
||||
colorWhite = drawing.Color{R: 241, G: 241, B: 241, A: 255}
|
||||
colorMariner = drawing.Color{R: 60, G: 100, B: 148, A: 255}
|
||||
colorLightSteelBlue = drawing.Color{R: 182, G: 195, B: 220, A: 255}
|
||||
colorPoloBlue = drawing.Color{R: 126, G: 155, B: 200, A: 255}
|
||||
colorSteelBlue = drawing.Color{R: 73, G: 120, B: 177, A: 255}
|
||||
)
|
||||
|
||||
stackedBarChart := chart.StackedBarChart{
|
||||
Title: "Quarterly Sales",
|
||||
TitleStyle: chart.StyleShow(),
|
||||
Background: chart.Style{
|
||||
Padding: chart.Box{
|
||||
Top: 75,
|
||||
},
|
||||
},
|
||||
Width: 800,
|
||||
Height: 600,
|
||||
XAxis: chart.StyleShow(),
|
||||
YAxis: chart.StyleShow(),
|
||||
BarSpacing: 40,
|
||||
IsHorizontal: true,
|
||||
Bars: []chart.StackedBar{
|
||||
{
|
||||
Name: "Q1",
|
||||
Width: barWidth,
|
||||
Values: []chart.Value{
|
||||
{
|
||||
Label: "32K",
|
||||
Value: 32,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorMariner,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "46K",
|
||||
Value: 46,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorLightSteelBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "48K",
|
||||
Value: 48,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorPoloBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "42K",
|
||||
Value: 42,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorSteelBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Q2",
|
||||
Width: barWidth,
|
||||
Values: []chart.Value{
|
||||
{
|
||||
Label: "45K",
|
||||
Value: 45,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorMariner,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "60K",
|
||||
Value: 60,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorLightSteelBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "62K",
|
||||
Value: 62,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorPoloBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "53K",
|
||||
Value: 53,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorSteelBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Q3",
|
||||
Width: barWidth,
|
||||
Values: []chart.Value{
|
||||
{
|
||||
Label: "54K",
|
||||
Value: 54,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorMariner,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "58K",
|
||||
Value: 58,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorLightSteelBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "55K",
|
||||
Value: 55,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorPoloBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "47K",
|
||||
Value: 47,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorSteelBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Q4",
|
||||
Width: barWidth,
|
||||
Values: []chart.Value{
|
||||
{
|
||||
Label: "46K",
|
||||
Value: 46,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorMariner,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "70K",
|
||||
Value: 70,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorLightSteelBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "74K",
|
||||
Value: 74,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorPoloBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "60K",
|
||||
Value: 60,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorSteelBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
pngFile, err := os.Create("output.png")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := stackedBarChart.Render(chart.PNG, pngFile); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := pngFile.Close(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
BIN
_examples/horizontal_stacked_bar/output.png
Normal file
BIN
_examples/horizontal_stacked_bar/output.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
221
_examples/stacked_bar_labels/main.go
Normal file
221
_examples/stacked_bar_labels/main.go
Normal file
|
@ -0,0 +1,221 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/wcharczuk/go-chart"
|
||||
"github.com/wcharczuk/go-chart/drawing"
|
||||
)
|
||||
|
||||
func main() {
|
||||
chart.DefaultBackgroundColor = chart.ColorTransparent
|
||||
chart.DefaultCanvasColor = chart.ColorTransparent
|
||||
|
||||
barWidth := 120
|
||||
|
||||
var (
|
||||
colorWhite = drawing.Color{R: 241, G: 241, B: 241, A: 255}
|
||||
colorMariner = drawing.Color{R: 60, G: 100, B: 148, A: 255}
|
||||
colorLightSteelBlue = drawing.Color{R: 182, G: 195, B: 220, A: 255}
|
||||
colorPoloBlue = drawing.Color{R: 126, G: 155, B: 200, A: 255}
|
||||
colorSteelBlue = drawing.Color{R: 73, G: 120, B: 177, A: 255}
|
||||
)
|
||||
|
||||
stackedBarChart := chart.StackedBarChart{
|
||||
Title: "Quarterly Sales",
|
||||
TitleStyle: chart.StyleShow(),
|
||||
Background: chart.Style{
|
||||
Padding: chart.Box{
|
||||
Top: 100,
|
||||
},
|
||||
},
|
||||
Width: 810,
|
||||
Height: 500,
|
||||
XAxis: chart.StyleShow(),
|
||||
YAxis: chart.StyleShow(),
|
||||
BarSpacing: 50,
|
||||
Bars: []chart.StackedBar{
|
||||
{
|
||||
Name: "Q1",
|
||||
Width: barWidth,
|
||||
Values: []chart.Value{
|
||||
{
|
||||
Label: "32K",
|
||||
Value: 32,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorMariner,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "46K",
|
||||
Value: 46,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorLightSteelBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "48K",
|
||||
Value: 48,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorPoloBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "42K",
|
||||
Value: 42,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorSteelBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Q2",
|
||||
Width: barWidth,
|
||||
Values: []chart.Value{
|
||||
{
|
||||
Label: "45K",
|
||||
Value: 45,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorMariner,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "60K",
|
||||
Value: 60,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorLightSteelBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "62K",
|
||||
Value: 62,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorPoloBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "53K",
|
||||
Value: 53,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorSteelBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Q3",
|
||||
Width: barWidth,
|
||||
Values: []chart.Value{
|
||||
{
|
||||
Label: "54K",
|
||||
Value: 54,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorMariner,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "58K",
|
||||
Value: 58,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorLightSteelBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "55K",
|
||||
Value: 55,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorPoloBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "47K",
|
||||
Value: 47,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorSteelBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Q4",
|
||||
Width: barWidth,
|
||||
Values: []chart.Value{
|
||||
{
|
||||
Label: "46K",
|
||||
Value: 46,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorMariner,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "70K",
|
||||
Value: 70,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorLightSteelBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "74K",
|
||||
Value: 74,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorPoloBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
{
|
||||
Label: "60K",
|
||||
Value: 60,
|
||||
Style: chart.Style{
|
||||
StrokeWidth: .01,
|
||||
FillColor: colorSteelBlue,
|
||||
FontColor: colorWhite,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
pngFile, err := os.Create("output.png")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := stackedBarChart.Render(chart.PNG, pngFile); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := pngFile.Close(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
BIN
_examples/stacked_bar_labels/output.png
Normal file
BIN
_examples/stacked_bar_labels/output.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
6
draw.go
6
draw.go
|
@ -296,8 +296,10 @@ func (d draw) TextWithin(r Renderer, text string, box Box, style Style) {
|
|||
switch style.GetTextVerticalAlign() {
|
||||
case TextVerticalAlignBottom, TextVerticalAlignBaseline: // i have to build better baseline handling into measure text
|
||||
y = y - linesBox.Height()
|
||||
case TextVerticalAlignMiddle, TextVerticalAlignMiddleBaseline:
|
||||
y = (y - linesBox.Height()) >> 1
|
||||
case TextVerticalAlignMiddle:
|
||||
y = y + (box.Height() >> 1) - (linesBox.Height() >> 1)
|
||||
case TextVerticalAlignMiddleBaseline:
|
||||
y = y + (box.Height() >> 1) - linesBox.Height()
|
||||
}
|
||||
|
||||
var tx, ty int
|
||||
|
|
|
@ -46,6 +46,8 @@ type StackedBarChart struct {
|
|||
Font *truetype.Font
|
||||
defaultFont *truetype.Font
|
||||
|
||||
IsHorizontal bool
|
||||
|
||||
Bars []StackedBar
|
||||
Elements []Renderable
|
||||
}
|
||||
|
@ -113,11 +115,20 @@ func (sbc StackedBarChart) Render(rp RendererProvider, w io.Writer) error {
|
|||
}
|
||||
r.SetDPI(sbc.GetDPI(DefaultDPI))
|
||||
|
||||
canvasBox := sbc.getAdjustedCanvasBox(r, sbc.getDefaultCanvasBox())
|
||||
sbc.drawCanvas(r, canvasBox)
|
||||
sbc.drawBars(r, canvasBox)
|
||||
sbc.drawXAxis(r, canvasBox)
|
||||
sbc.drawYAxis(r, canvasBox)
|
||||
var canvasBox Box
|
||||
if sbc.IsHorizontal {
|
||||
canvasBox = sbc.getHorizontalAdjustedCanvasBox(r, sbc.getDefaultCanvasBox())
|
||||
sbc.drawCanvas(r, canvasBox)
|
||||
sbc.drawHorizontalBars(r, canvasBox)
|
||||
sbc.drawHorizontalXAxis(r, canvasBox)
|
||||
sbc.drawHorizontalYAxis(r, canvasBox)
|
||||
} else {
|
||||
canvasBox = sbc.getAdjustedCanvasBox(r, sbc.getDefaultCanvasBox())
|
||||
sbc.drawCanvas(r, canvasBox)
|
||||
sbc.drawBars(r, canvasBox)
|
||||
sbc.drawXAxis(r, canvasBox)
|
||||
sbc.drawYAxis(r, canvasBox)
|
||||
}
|
||||
|
||||
sbc.drawTitle(r)
|
||||
for _, a := range sbc.Elements {
|
||||
|
@ -139,6 +150,14 @@ func (sbc StackedBarChart) drawBars(r Renderer, canvasBox Box) {
|
|||
}
|
||||
}
|
||||
|
||||
func (sbc StackedBarChart) drawHorizontalBars(r Renderer, canvasBox Box) {
|
||||
yOffset := canvasBox.Top
|
||||
for _, bar := range sbc.Bars {
|
||||
sbc.drawHorizontalBar(r, canvasBox, yOffset, bar)
|
||||
yOffset += sbc.GetBarSpacing() + bar.GetWidth()
|
||||
}
|
||||
}
|
||||
|
||||
func (sbc StackedBarChart) drawBar(r Renderer, canvasBox Box, xoffset int, bar StackedBar) int {
|
||||
barSpacing2 := sbc.GetBarSpacing() >> 1
|
||||
bxl := xoffset + barSpacing2
|
||||
|
@ -158,9 +177,85 @@ func (sbc StackedBarChart) drawBar(r Renderer, canvasBox Box, xoffset int, bar S
|
|||
yoffset += barHeight
|
||||
}
|
||||
|
||||
// draw the labels
|
||||
yoffset = canvasBox.Top
|
||||
var lx, ly int
|
||||
for index, bv := range normalizedBarComponents {
|
||||
barHeight := int(math.Ceil(bv.Value * float64(canvasBox.Height())))
|
||||
|
||||
if len(bv.Label) > 0 {
|
||||
lx = bxl + ((bxr - bxl) / 2)
|
||||
ly = yoffset + (barHeight / 2)
|
||||
|
||||
bv.Style.InheritFrom(sbc.styleDefaultsStackedBarValue(index)).WriteToRenderer(r)
|
||||
tb := r.MeasureText(bv.Label)
|
||||
lx = lx - (tb.Width() >> 1)
|
||||
ly = ly + (tb.Height() >> 1)
|
||||
|
||||
if lx < 0 {
|
||||
lx = 0
|
||||
}
|
||||
if ly < 0 {
|
||||
lx = 0
|
||||
}
|
||||
|
||||
r.Text(bv.Label, lx, ly)
|
||||
}
|
||||
yoffset += barHeight
|
||||
}
|
||||
|
||||
return bxr
|
||||
}
|
||||
|
||||
func (sbc StackedBarChart) drawHorizontalBar(r Renderer, canvasBox Box, yoffset int, bar StackedBar) {
|
||||
halfBarSpacing := sbc.GetBarSpacing() >> 1
|
||||
|
||||
boxTop := yoffset + halfBarSpacing
|
||||
boxBottom := boxTop + bar.GetWidth()
|
||||
|
||||
normalizedBarComponents := Values(bar.Values).Normalize()
|
||||
|
||||
xOffset := canvasBox.Right
|
||||
for index, bv := range normalizedBarComponents {
|
||||
barHeight := int(math.Ceil(bv.Value * float64(canvasBox.Width())))
|
||||
barBox := Box{
|
||||
Top: boxTop,
|
||||
Left: MinInt(xOffset-barHeight, canvasBox.Left+DefaultStrokeWidth),
|
||||
Right: xOffset,
|
||||
Bottom: boxBottom,
|
||||
}
|
||||
Draw.Box(r, barBox, bv.Style.InheritFrom(sbc.styleDefaultsStackedBarValue(index)))
|
||||
xOffset -= barHeight
|
||||
}
|
||||
|
||||
// draw the labels
|
||||
xOffset = canvasBox.Right
|
||||
var lx, ly int
|
||||
for index, bv := range normalizedBarComponents {
|
||||
barHeight := int(math.Ceil(bv.Value * float64(canvasBox.Width())))
|
||||
|
||||
if len(bv.Label) > 0 {
|
||||
lx = xOffset - (barHeight / 2)
|
||||
ly = boxTop + ((boxBottom - boxTop) / 2)
|
||||
|
||||
bv.Style.InheritFrom(sbc.styleDefaultsStackedBarValue(index)).WriteToRenderer(r)
|
||||
tb := r.MeasureText(bv.Label)
|
||||
lx = lx - (tb.Width() >> 1)
|
||||
ly = ly + (tb.Height() >> 1)
|
||||
|
||||
if lx < 0 {
|
||||
lx = 0
|
||||
}
|
||||
if ly < 0 {
|
||||
lx = 0
|
||||
}
|
||||
|
||||
r.Text(bv.Label, lx, ly)
|
||||
}
|
||||
xOffset -= barHeight
|
||||
}
|
||||
}
|
||||
|
||||
func (sbc StackedBarChart) drawXAxis(r Renderer, canvasBox Box) {
|
||||
if !sbc.XAxis.Hidden {
|
||||
axisStyle := sbc.XAxis.InheritFrom(sbc.styleDefaultsAxes())
|
||||
|
@ -195,6 +290,42 @@ func (sbc StackedBarChart) drawXAxis(r Renderer, canvasBox Box) {
|
|||
}
|
||||
}
|
||||
|
||||
func (sbc StackedBarChart) drawHorizontalXAxis(r Renderer, canvasBox Box) {
|
||||
if !sbc.XAxis.Hidden {
|
||||
axisStyle := sbc.XAxis.InheritFrom(sbc.styleDefaultsAxes())
|
||||
axisStyle.WriteToRenderer(r)
|
||||
r.MoveTo(canvasBox.Left, canvasBox.Bottom)
|
||||
r.LineTo(canvasBox.Right, canvasBox.Bottom)
|
||||
r.Stroke()
|
||||
|
||||
r.MoveTo(canvasBox.Left, canvasBox.Bottom)
|
||||
r.LineTo(canvasBox.Left, canvasBox.Bottom+DefaultVerticalTickHeight)
|
||||
r.Stroke()
|
||||
|
||||
ticks := LinearRangeWithStep(0.0, 1.0, 0.2)
|
||||
for _, t := range ticks {
|
||||
axisStyle.GetStrokeOptions().WriteToRenderer(r)
|
||||
tx := canvasBox.Left + int(t*float64(canvasBox.Width()))
|
||||
r.MoveTo(tx, canvasBox.Bottom)
|
||||
r.LineTo(tx, canvasBox.Bottom+DefaultVerticalTickHeight)
|
||||
r.Stroke()
|
||||
|
||||
axisStyle.GetTextOptions().WriteToRenderer(r)
|
||||
text := fmt.Sprintf("%0.0f%%", t*100)
|
||||
|
||||
textBox := r.MeasureText(text)
|
||||
textX := tx - (textBox.Width() >> 1)
|
||||
textY := canvasBox.Bottom + DefaultXAxisMargin + 10
|
||||
|
||||
if t == 1 {
|
||||
textX = canvasBox.Right - textBox.Width()
|
||||
}
|
||||
|
||||
Draw.Text(r, text, textX, textY, axisStyle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sbc StackedBarChart) drawYAxis(r Renderer, canvasBox Box) {
|
||||
if !sbc.YAxis.Hidden {
|
||||
axisStyle := sbc.YAxis.InheritFrom(sbc.styleDefaultsAxes())
|
||||
|
@ -221,7 +352,39 @@ func (sbc StackedBarChart) drawYAxis(r Renderer, canvasBox Box) {
|
|||
tb := r.MeasureText(text)
|
||||
Draw.Text(r, text, canvasBox.Right+DefaultYAxisMargin+5, ty+(tb.Height()>>1), axisStyle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sbc StackedBarChart) drawHorizontalYAxis(r Renderer, canvasBox Box) {
|
||||
if !sbc.YAxis.Hidden {
|
||||
axisStyle := sbc.YAxis.InheritFrom(sbc.styleDefaultsHorizontalAxes())
|
||||
axisStyle.WriteToRenderer(r)
|
||||
|
||||
r.MoveTo(canvasBox.Left, canvasBox.Bottom)
|
||||
r.LineTo(canvasBox.Left, canvasBox.Top)
|
||||
r.Stroke()
|
||||
|
||||
r.MoveTo(canvasBox.Left, canvasBox.Bottom)
|
||||
r.LineTo(canvasBox.Left-DefaultHorizontalTickWidth, canvasBox.Bottom)
|
||||
r.Stroke()
|
||||
|
||||
cursor := canvasBox.Top
|
||||
for _, bar := range sbc.Bars {
|
||||
barLabelBox := Box{
|
||||
Top: cursor,
|
||||
Left: 0,
|
||||
Right: canvasBox.Left - DefaultYAxisMargin,
|
||||
Bottom: cursor + bar.GetWidth() + sbc.GetBarSpacing(),
|
||||
}
|
||||
if len(bar.Name) > 0 {
|
||||
Draw.TextWithin(r, bar.Name, barLabelBox, axisStyle)
|
||||
}
|
||||
axisStyle.WriteToRenderer(r)
|
||||
r.MoveTo(canvasBox.Left, barLabelBox.Bottom)
|
||||
r.LineTo(canvasBox.Left-DefaultHorizontalTickWidth, barLabelBox.Bottom)
|
||||
r.Stroke()
|
||||
cursor += bar.GetWidth() + sbc.GetBarSpacing()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -311,6 +474,48 @@ func (sbc StackedBarChart) getAdjustedCanvasBox(r Renderer, canvasBox Box) Box {
|
|||
|
||||
}
|
||||
|
||||
func (sbc StackedBarChart) getHorizontalAdjustedCanvasBox(r Renderer, canvasBox Box) Box {
|
||||
var totalHeight int
|
||||
for _, bar := range sbc.Bars {
|
||||
totalHeight += bar.GetWidth() + sbc.GetBarSpacing()
|
||||
}
|
||||
|
||||
if !sbc.YAxis.Hidden {
|
||||
yAxisWidth := DefaultHorizontalTickWidth
|
||||
|
||||
axisStyle := sbc.YAxis.InheritFrom(sbc.styleDefaultsHorizontalAxes())
|
||||
axisStyle.WriteToRenderer(r)
|
||||
|
||||
cursor := canvasBox.Top
|
||||
for _, bar := range sbc.Bars {
|
||||
if len(bar.Name) > 0 {
|
||||
barLabelBox := Box{
|
||||
Top: cursor,
|
||||
Left: 0,
|
||||
Right: canvasBox.Left + DefaultYAxisMargin,
|
||||
Bottom: cursor + bar.GetWidth() + sbc.GetBarSpacing(),
|
||||
}
|
||||
lines := Text.WrapFit(r, bar.Name, barLabelBox.Width(), axisStyle)
|
||||
linesBox := Text.MeasureLines(r, lines, axisStyle)
|
||||
|
||||
yAxisWidth = MaxInt(linesBox.Height()+(2*DefaultXAxisMargin), yAxisWidth)
|
||||
}
|
||||
}
|
||||
return Box{
|
||||
Top: canvasBox.Top,
|
||||
Left: canvasBox.Left + yAxisWidth,
|
||||
Right: canvasBox.Right,
|
||||
Bottom: canvasBox.Top + totalHeight,
|
||||
}
|
||||
}
|
||||
return Box{
|
||||
Top: canvasBox.Top,
|
||||
Left: canvasBox.Left,
|
||||
Right: canvasBox.Right,
|
||||
Bottom: canvasBox.Top + totalHeight,
|
||||
}
|
||||
}
|
||||
|
||||
// Box returns the chart bounds as a box.
|
||||
func (sbc StackedBarChart) Box() Box {
|
||||
dpr := sbc.Background.Padding.GetRight(10)
|
||||
|
@ -329,6 +534,9 @@ func (sbc StackedBarChart) styleDefaultsStackedBarValue(index int) Style {
|
|||
StrokeColor: sbc.GetColorPalette().GetSeriesColor(index),
|
||||
StrokeWidth: 3.0,
|
||||
FillColor: sbc.GetColorPalette().GetSeriesColor(index),
|
||||
FontSize: sbc.getScaledFontSize(),
|
||||
FontColor: sbc.GetColorPalette().TextColor(),
|
||||
Font: sbc.GetFont(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -343,6 +551,20 @@ func (sbc StackedBarChart) styleDefaultsTitle() Style {
|
|||
})
|
||||
}
|
||||
|
||||
func (sbc StackedBarChart) getScaledFontSize() float64 {
|
||||
effectiveDimension := MinInt(sbc.GetWidth(), sbc.GetHeight())
|
||||
if effectiveDimension >= 2048 {
|
||||
return 48.0
|
||||
} else if effectiveDimension >= 1024 {
|
||||
return 24.0
|
||||
} else if effectiveDimension > 512 {
|
||||
return 18.0
|
||||
} else if effectiveDimension > 256 {
|
||||
return 12.0
|
||||
}
|
||||
return 10.0
|
||||
}
|
||||
|
||||
func (sbc StackedBarChart) getTitleFontSize() float64 {
|
||||
effectiveDimension := MinInt(sbc.GetWidth(), sbc.GetHeight())
|
||||
if effectiveDimension >= 2048 {
|
||||
|
@ -368,6 +590,19 @@ func (sbc StackedBarChart) styleDefaultsAxes() Style {
|
|||
TextWrap: TextWrapWord,
|
||||
}
|
||||
}
|
||||
|
||||
func (sbc StackedBarChart) styleDefaultsHorizontalAxes() Style {
|
||||
return Style{
|
||||
StrokeColor: DefaultAxisColor,
|
||||
Font: sbc.GetFont(),
|
||||
FontSize: DefaultAxisFontSize,
|
||||
FontColor: DefaultAxisColor,
|
||||
TextHorizontalAlign: TextHorizontalAlignCenter,
|
||||
TextVerticalAlign: TextVerticalAlignMiddle,
|
||||
TextWrap: TextWrapWord,
|
||||
}
|
||||
}
|
||||
|
||||
func (sbc StackedBarChart) styleDefaultsElements() Style {
|
||||
return Style{
|
||||
Font: sbc.GetFont(),
|
||||
|
|
2
text.go
2
text.go
|
@ -46,7 +46,7 @@ const (
|
|||
TextVerticalAlignBottom TextVerticalAlign = 2
|
||||
// TextVerticalAlignMiddle aligns the text so that there is an equal amount of space above and below the top and bottom of the ligatures.
|
||||
TextVerticalAlignMiddle TextVerticalAlign = 3
|
||||
// TextVerticalAlignMiddleBaseline aligns the text veritcally so that there is an equal number of pixels above and below the baseline of the string.
|
||||
// TextVerticalAlignMiddleBaseline aligns the text vertically so that there is an equal number of pixels above and below the baseline of the string.
|
||||
TextVerticalAlignMiddleBaseline TextVerticalAlign = 4
|
||||
// TextVerticalAlignTop alignts the text so that the top of the ligatures are at y-pixel 0 in the container.
|
||||
TextVerticalAlignTop TextVerticalAlign = 5
|
||||
|
|
Loading…
Reference in a new issue