SVG can draws text as we do in canvas. It’s a common task to center a text block. Text block can span multiple lines.
Since in SVG, the viewport origin is at the top-left corner, we can use similar transform: translate
trick in CSS.
package main
import (
"encoding/xml"
"fmt"
"net/http"
"strings"
svg "github.com/ajstarks/svgo"
)
func main() {
lines := []string{
"meaningful work and",
"meaningful relationships",
"aren't just nice thins we",
"chose for ourselves",
"-- they are genetically",
"program into us.",
}
for idx := range lines {
lines[idx] = strings.ToUpper(lines[idx])
}
http.HandleFunc("/", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "image/svg+xml")
width := 600
height := 600
fontSize := 32
canvas := svg.New(w)
canvas.Start(width, height)
canvas.Def()
canvas.Style("text/css", "@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap');")
canvas.DefEnd()
canvas.Rect(0, 0, width, height, "fill:red")
canvas.Gstyle(fmt.Sprintf("font-size:%dpx;fill:white;text-anchor:middle;font-family:Roboto", fontSize))
fmt.Fprintf(
canvas.Writer,
`<text x="50%%" y="50%%" transform="translate(0, %d)">`,
-len(lines)*fontSize/2,
)
for _, line := range lines {
fmt.Fprintf(
canvas.Writer,
`<tspan x="50%%" dy="%d">`,
fontSize,
)
xml.Escape(canvas.Writer, []byte(line))
fmt.Fprintf(
canvas.Writer,
`</tspan>`,
)
}
fmt.Fprintf(
canvas.Writer,
`</text>`,
)
canvas.Gend()
canvas.End()
}))
if err := http.ListenAndServe(":3333", nil); err != nil {
panic(err)
}
}