为了传播拉新,需要海报图。一般情况下是前端生成:Canvas。但是,这次重担交给服务端了,能不能胜任?能,只要时间足够充裕,我可以慢慢学,调试(你看看,这工作态度。绝对的优秀员工)
Imaging 是一个强大的图像处理库,提供了各种图像操作的功能,包括调整大小、裁剪、旋转、模糊、锐化、颜色调整等。
主要功能:
gg 是一个简单的 2D 绘图库,基于 cairo 提供了更方便的 API,用于生成和操作图形。它特别适合生成图表、图形叠加、文字和图形组合等任务。
主要功能:
font 提供了与字体相关的功能,包括字体加载、字体渲染等。这个包定义了字体的基本接口和数据结构。
主要功能:
opentype 专门用于处理 OpenType 字体格式,提供了加载和渲染 OpenType 字体的功能。
主要功能:
image/color 包定义了表示颜色的接口和类型。它提供了各种颜色模型和用于转换颜色的实用函数。
主要功能:
实现一个按钮,要求是椭圆型,文字居中。
参数信息: boxW := 600 boxH := 300 boxColor := color.RGBA{R: 255, G: 255, B: 255, A: 1} buttonW := 200 buttonH := 100 ButtonColor := "#8650ac" fontSize := 48 fontDpi := 96.0 buttonText := "按钮" fontColor := "#ffffff" buttonImg := "./img/button.jpg"
物料:
下载字体资源文件:
package mainimport ( "context" "fmt" "github.com/disintegration/imaging" "github.com/fogleman/gg" "golang.org/x/image/font" "golang.org/x/image/font/opentype" "image/color" "os")type DrawText struct {}type drawText interface { // DrawButton 绘制按钮 DrawButton(ctx context.Context, w, y float64, color string, boxColor color.Color) (data *gg.Context, err error) // LoadFont 加载字体 LoadFont(fontSize float64, dpi float64) (fontFace font.Face, err error) // PxToPt PxToPt PxToPt(px float64, dpi float64) float64 // SaveImg 保存图片 SaveImg(dc *gg.Context, fileName string) bool}func NewDrawText(ctx context.Context) drawText { return &DrawText{}}func main() { boxW := 600 boxH := 300 boxColor := color.RGBA{R: 255, G: 255, B: 255, A: 1} buttonW := 200 buttonH := 100 ButtonColor := "#8650ac" fontSize := 48 fontDpi := 96.0 buttonText := "按钮" fontColor := "#ffffff" buttonImg := "./img/button.jpg" d := NewDrawText(context.Background()) // 创建一个大的画布 dc := gg.NewContext(boxW, boxH) dc.SetColor(boxColor) // Set background color dc.Clear() // 绘制色块 dcButton, err := d.DrawButton(context.Background(), float64(buttonW), float64(buttonH), ButtonColor, boxColor) if err != nil { panic(err) return } // 加载字体 fontFace, err := d.LoadFont(d.PxToPt(float64(fontSize), fontDpi), fontDpi) if err != nil { panic(err) return } defer fontFace.Close() // 设置字体参数、颜色 dcButton.SetFontFace(fontFace) dcButton.SetHexColor(fontColor) // 字体文案,计算x,y 居中位置 buttonTextW, buttonTextH := dcButton.MeasureString(buttonText) dcButton.DrawString(buttonText, (float64(buttonW)-buttonTextW)/2, (float64(buttonH)+buttonTextH)*2/5) // 按钮绘制到画布上 dc.DrawImage(dcButton.Image(), (boxW-buttonW)/2, (boxH-buttonH)/2) if d.SaveImg(dc, buttonImg) { return } fmt.Println("done") return}func (d *DrawText) SaveImg(dc *gg.Context, fileName string) bool { if err := imaging.Save(dc.Image(), fileName); err != nil { panic(err) return true } fmt.Printf("保持为jpg图片:%s\n", fileName) return false}// LoadFont 加载字体func (d *DrawText) LoadFont(fontSize float64, dpi float64) (fontFace font.Face, err error) { fontBytes, err := os.ReadFile("./assets/Source_Han_Sans_SC_Normal_Normal.otf") if err != nil { return nil, fmt.Errorf("failed to read font file: %w", err) } fontVal, err := opentype.Parse(fontBytes) if err != nil { return nil, fmt.Errorf("failed to parse font: %w", err) } fontFace, err = opentype.NewFace(fontVal, &opentype.FaceOptions{ Size: fontSize, DPI: dpi, Hinting: font.HintingFull, }) if err != nil { return nil, fmt.Errorf("failed to create font face: %w", err) } return fontFace, nil}// DrawButton 绘制色块func (d *DrawText) DrawButton(ctx context.Context, w, y float64, color string, boxColor color.Color) (data *gg.Context, err error) { // 创建一个上下文来绘制色块 dc := gg.NewContext(int(w), int(y)) // 设置背景颜色 同画布颜色 dc.SetColor(boxColor) // 填充颜色 dc.Clear() // 设置圆角 dc.SetHexColor(color) dc.DrawRoundedRectangle(0, 0, w, y, 20) dc.Fill() return dc, nil}func (d *DrawText) PxToPt(px float64, dpi float64) float64 { return px * (72 / dpi)}
麻雀虽小,五脏俱全。想实现其他功能,自由组合。
海报图生成,最麻烦的就是计算,从始至终,就是拿着计算器计算,调整X,Y坐标。还有一点就是,px和pt的转化,不同的设备,分辨率展示出的效果不同。前端可以获取到客户端的设备信息,服务端拿不到这些数据,只能按照经验值去设定。
我为人人,人人为我。美美与共,天下大同。