使用Go语言实现类似placeholder.com的动态尺寸图片及尺寸文本绘制
在Go生成的占位图片上动态绘制尺寸文本
你已经搞定了基础的灰色背景生成,接下来要解决的就是动态适配图片尺寸的文本绘制——这也是placeholder.com那种效果的核心:文本大小、位置都能跟着图片宽高自动调整,不会出现文字太大溢出或者太小看不清的情况。
我给你整理了一套完整的实现方案,直接就能用:
核心思路
- 选择适配性强的字体(可以用系统基础字体,也能嵌入开源字体避免外部依赖)
- 根据图片宽高的最小边计算合适的文本字号,保证文本能完整显示
- 精准计算文本的居中绘制位置,避免偏移
- 用Go的
image/draw和golang.org/x/image/font系列包完成文本渲染
完整代码示例
package main import ( "fmt" "image" "image/color" "image/draw" "image/png" "os" "golang.org/x/image/font" "golang.org/x/image/font/basicfont" "golang.org/x/image/math/fixed" ) func main() { width := 350 height := 150 // 创建灰色背景图:修正Alpha通道为255(完全不透明) img := image.NewRGBA(image.Rect(0, 0, width, height)) bgColor := color.RGBA{204, 204, 204, 255} draw.Draw(img, img.Bounds(), &image.Uniform{bgColor}, image.Point{}, draw.Src) // 生成要绘制的尺寸文本 text := fmt.Sprintf("%d×%d", width, height) // 动态计算字号:取图片最小边的1/8作为基准,可按需调整比例 fontSizeRatio := 8.0 fontSize := float64(min(width, height)) / fontSizeRatio face := basicfont.Face7x13 // 先使用基础字体,后续可替换为自定义字体 // 计算文本实际占用的尺寸 d := &font.Drawer{ Dst: img, Src: &image.Uniform{color.RGBA{0, 0, 0, 255}}, // 黑色文本 Face: face, } d.Dot = fixed.P(0, 0) textBounds, _ := d.BoundString(text) textWidth := int(textBounds.Max.X - textBounds.Min.X) textHeight := int(textBounds.Max.Y - textBounds.Min.Y) // 计算居中绘制坐标:X轴水平居中,Y轴基于字体基线调整实现垂直居中 x := (width - textWidth) / 2 y := (height + textHeight) / 2 // 设置绘制位置并渲染文本 d.Dot = fixed.P(x, y) d.DrawString(text) // 保存图片到本地 f, err := os.Create("placeholder.png") if err != nil { panic(err) } defer f.Close() png.Encode(f, img) } // 辅助函数:取两个整数的最小值 func min(a, b int) int { if a < b { return a } return b }
关键细节说明
- Alpha通道修正:你之前代码里的
color.RGBA{204,204,204,1}几乎是透明状态,改成255才能显示正常的灰色背景 - 动态字号逻辑:用图片最小边的比例计算字号,不管是宽幅图还是竖幅图,文本都能适配不溢出
- 垂直居中技巧:字体的绘制基线在Y轴位置,所以Y坐标不能直接用
height/2,而是(height + textHeight)/2,这样文本才能真正垂直居中 - 自定义字体替换:如果觉得基础字体不够美观,可以换成TTF字体,示例代码如下:
// 加载自定义TTF字体示例(需要引入opentype包) import "golang.org/x/image/font/opentype" fontBytes, err := os.ReadFile("Roboto-Regular.ttf") if err != nil { panic(err) } f, err := opentype.Parse(fontBytes) if err != nil { panic(err) } face, err := opentype.NewFace(f, &opentype.FaceOptions{ Size: fontSize, DPI: 72, Hinting: font.HintingFull, }) if err != nil { panic(err) } defer face.Close()
这样生成的图片就和placeholder.com的效果完全一致了,文本会自动适配图片尺寸,精准居中显示~
内容的提问来源于stack exchange,提问作者Jared Chu
相关产品推荐
相关产品推荐

