利用周末写一个小工具:多设备预览图生成

起因是这样的,每次在调整完自己网站的时候,对于一些 UI 样式的调整,都需要提交代码并构建好后,通过第三方的预览图生成网站或者手动修图来制作一个网站预览图并重新上传提交代码。 这样似乎有些繁琐了,尝试寻求一个完美的工具来达到这个目的,但在 github 上寻一圈未果,所以就利用这个周末去写一个简单的工具来实现这个需求。

效果图

先来预览下效果图:

需求分析

  1. 收集多设备的外壳图片素材,必须带有透明通道,方便后续图片的合并
  2. 获取设备图片的屏幕尺寸(宽·高),截图的大小需贴合设备图片的尺寸
  3. 获取网页截图,需根据设备 UA 进行读取网页(这里使用 chromedp),然后裁剪成设备屏幕的尺寸
  4. 创建一个大的画布,将截图贴到画布上,接着将设备图片贴到截图上(这里需要考虑设备最终在画布上的坐标位置)
  5. 考虑 IPhone 设备的四角非直角,所以需要特殊处理下,将设备图片的圆角部分进行裁剪

实现思路

Step 1

利用 chromedp 包,读取本机带有 Chromium 内核的浏览器,初始化浏览器分配上下文,采用无头模式

ps:这里仅展示核心逻辑,完整代码请下滑到最底移步到 github 仓库查看

go 复制代码
// 初始化浏览器分配器上下文
browserPath, err := "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe"
opts := append(chromedp.DefaultExecAllocatorOptions[:],
    chromedp.ExecPath(browserPath),
    chromedp.NoFirstRun,
    chromedp.NoDefaultBrowserCheck,
    chromedp.Headless,
)
allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
defer cancel()

并发读取网页,获取网页截图

go 复制代码
func takeScreenshotForDevice(ctx context.Context, url string, width, height int) (*image.RGBA, error) {
    var buf []byte
    
    err := chromedp.Run(ctx,
        chromedp.EmulateViewport(int64(width), int64(height)),
        chromedp.Navigate(url),
        chromedp.Sleep(3*time.Second),
        chromedp.WaitVisible("body", chromedp.ByQuery),
        chromedp.CaptureScreenshot(&buf),
    )
    if err != nil {
        return nil, err
    }

    img, _, err := image.Decode(bytes.NewReader(buf))
    if err != nil {
       return nil, err
    }

    bounds := img.Bounds()
    rgba := image.NewRGBA(bounds)
    draw.Draw(rgba, bounds, img, bounds.Min, draw.Src)

    return rgba, nil
}

Step 2

创建画布

go 复制代码
canvas := imaging.New(2560, 1600, color.White)

Step 3

遍历所有截图并贴入画布,同时将设备外壳覆盖到截图上

ps:这里逻辑取值较复杂,故省略代码

go 复制代码
for _, dev := range Devices {
    ...
    // 读取设备图片
    ...

    // 解码图片数据
    ...

    // 转换为 RGBA 格式以便绘制
    ...

    // 将外壳覆盖到画布的对应位置(LayoutX/Y)
    ...
}

Step 4

保存并输出

go 复制代码
outFile := "output/preview.png"

f, err := os.Create(outFile)
if err != nil {
    panic(err)
}
defer f.Close()

if err := png.Encode(f, canvas); err != nil {
    panic(err)
}

fmt.Println("预览图生成成功:", outFile)

总结

复杂点

  • 设备在画布中的位置计算,以及截图的裁剪位置计算
  • 设备图片的圆角处理,这里用 ai 给的代码做了处理,也算是被 ai 坑了一回,四角虽做了处理,但是并没有透明化,也是耗费了很长时间才弄懂图片透明逻辑的处理

不足点

  • 访问页面未设置超时,对于一些网站访问会比较慢,可能会导致卡死,不过访问本地页面处理速度还是很快的,这里后续有时间优化下
  • 截图有时候内容会加载不全,问题同上

最后

源码已上传至 github 仓库:GitHub - vespeng/multi-device-preview,欢迎 fork 和 star。

相关推荐
RWKV元始智能7 小时前
RWKV超并发项目教程,RWKV-LM训练提速40%
人工智能·rnn·深度学习·自然语言处理·开源
Hommy888 小时前
【开源剪映小助手】API 接口文档
开源·github·aigc·视频剪辑自动化·剪映api
一粒黑子8 小时前
【实战解析】阿里开源 PageAgent:纯前端 GUI Agent,一行JS让网页支持自然语言操控
前端·javascript·开源
码途漫谈8 小时前
Easy-Vibe开发篇阅读笔记(四)——前端开发之结合 Agent Skills 美化界面
人工智能·笔记·ai·开源·ai编程
小码哥_常8 小时前
解锁AI编程密码:程序员常用的10个AI提示词
后端
GitCode官方9 小时前
小米 MiMo‑V2.5 系列开源,正式入驻 AtomGit!旗舰模型完成全球多家主流芯⽚⼚商深度适配
开源·小米·atomgit
直奔標竿9 小时前
Java开发者AI转型第二十七课!Spring AI 个人知识库实战(六)——全栈闭环收官,解锁前端流式渲染终极技巧
java·开发语言·前端·人工智能·后端·spring
审判长烧鸡9 小时前
GO时区【2】跨时区应用
go·存储·时区
金銀銅鐵10 小时前
[java] 编译之后的记录类(Record Classes)长什么样子(上)
java·jvm·后端
审判长烧鸡10 小时前
Go结构体与指针【2】接收者应该怎么用
go·指针·结构体·接收者