如何打造一款多设备预览图的神器?
- 内容介绍
- 文章标签
- 相关推荐
功力不足。 说实话,我之前搞网页截图的时候,用的还是手动截图的老办法。每次调整完网站的UI样式, 都得提交代码,等待把网页截图贴进去。这流程简直让人抓狂。
让我们一起... 我就在想,有没有什么办法能让这个过程自动化?于是乎,我开始了我的周末“小项目”。目标很明确:打造一个本地化、快速、还能随心所欲定制的预览图生成工具。
第一步:选择合适的工具
要实现网页截图,核心能力无非是控制浏览器。Python有Selenium,Node有Puppeteer,但我到头来选择了Go语言。 礼貌吗? 为什么?主要原因是Go的并发特性太适合这种场景了——想象一下一边启动十几个无头浏览器去抓取不同设备的截图,那效率杠杠的。
这事儿我可太有发言权了。 在控制浏览器方面chromedp 这个库绝对是Go语言生态里的王者。它不需要依赖外部的ChromeDriver, 直接通过CDP协议与Chromium内核通信,既轻量又稳定。
初始化浏览器环境
初始化的代码大概长这样:
// 初始化浏览器分配器上下文 browserPath, err := "C:\Program Files \Microsoft\Edge\Application\msedge.exe" opts := append(chromedp.DefaultExecAllocatorOptions, chromedp.ExecPath, chromedp.NoFirstRun, chromedp.NoDefaultBrowserCheck, chromedp.Headless, ) allocCtx, cancel := chromedp.NewExecAllocator, opts...) defer cancel,最终的最终。
话虽然是这么说… 这段代码就像是给浏览器下达了“静音指令”, 告诉它:“别废话,干活就是了。”
第二步:模拟不同设备并截图
拿到了浏览器环境,接下来就是最关键的一步:怎么把网页“画”下来。我们不能简单地截个全屏, 主要原因是我们要模拟的是不同的设备——iPhone SE、iPad Pro、Desktop 1080p等等。这就涉及到视口的模拟,我emo了。。
这里我封装了一个函数takeScreenshotForDevice 它接收URL、宽度和高度作为参数。利用chromedp.EmulateViewport 我们可以欺骗浏览器, 他破防了。 让它以为自己正运行在不同尺寸的屏幕上。
func takeScreenshotForDevice {
var buf byte
err := chromedp.Run(ctx,
chromedp.EmulateViewport, int64),
chromedp.Navigate,
chromedp.Sleep, // 稍微留点时间让JS跑一跑
chromedp.WaitVisible,
chromedp.CaptureScreenshot,
)
if err != nil {
return nil, err
}
img, _, err := image.Decode)
if err != nil {
return nil, err
}
bounds := img.Bounds
rgba := image.NewRGBA
draw.Draw
return rgba, nil
}
图像处理与合成
拿到了所有设备的截图,这只是半成品。为了让预览图看起来像那么回事,我们需要把这些截图“塞”进真实的设备外壳里。这就好比给手机贴膜,得严丝合缝才行。
先说说我们需要创建一个足够大的画布。背景色我选了纯白,这样看起来比较干净。这里用到了imaging库,它比标准库的image提供了更多便捷的图像处理方法。
摆烂。 canvas := imaging.New
接下来就是最繁琐但也最有成就感的环节:遍历所有设备。对于每一个设备,我们都要做三件事:读取设备图片、 地道。 解码图片数据、转换为 RGBA 格式以便绘制。
再说说一步:拼贴画布
定位与绘制根据预设的布局坐标,先把刚才截取的网页内容画到底层。然后覆盖外壳再说说把设备外壳盖在最上面。 闹乌龙。 这一步必须精准,否则屏幕内容就会错位,看起来非常滑稽。
我个人认为... for _, dev := range Devices { ... // 读取设备图片 ... // 解码图片数据 ... // 转换为 RGBA 格式以便绘制 ... // 将外壳覆盖到画布的对应位置 ... }
当循环结束, 一张包含iPhone、iPad、MacBook等多设备展示的精美预览图就静静地躺在内存里了。再说说一步,自然是把这个杰作保存到磁盘上。创建文件流,调用PNG编码,大功告成,PTSD了...!
outFile := "output/preview.png" f, err := os.Create if err != nil { panic } defer f.Close if err := png.Encode; err != nil { panic } fmt.Println,拯救一下。
这个周末的小项目, 虽然代码量不算巨大,但解决了我实实在在的痛点。从一开始的一时兴起,到查文档、写代码、调Bug,再说说看着生成的预览图,那种成就感是难以言喻的。
也是没谁了。 虽然这个工具已经能满足我当下的需求, 但作为一个有追求的开发者,我心里清楚它还不够完美。比如现在的并发虽然快,但对机器内存的消耗也不小。如果一边开几十个无头浏览器实例,普通的笔记本估计得冒烟。未来或许可以考虑引入任务队列,限制并发数,做一个更优雅的调度器。
功力不足。 说实话,我之前搞网页截图的时候,用的还是手动截图的老办法。每次调整完网站的UI样式, 都得提交代码,等待把网页截图贴进去。这流程简直让人抓狂。
让我们一起... 我就在想,有没有什么办法能让这个过程自动化?于是乎,我开始了我的周末“小项目”。目标很明确:打造一个本地化、快速、还能随心所欲定制的预览图生成工具。
第一步:选择合适的工具
要实现网页截图,核心能力无非是控制浏览器。Python有Selenium,Node有Puppeteer,但我到头来选择了Go语言。 礼貌吗? 为什么?主要原因是Go的并发特性太适合这种场景了——想象一下一边启动十几个无头浏览器去抓取不同设备的截图,那效率杠杠的。
这事儿我可太有发言权了。 在控制浏览器方面chromedp 这个库绝对是Go语言生态里的王者。它不需要依赖外部的ChromeDriver, 直接通过CDP协议与Chromium内核通信,既轻量又稳定。
初始化浏览器环境
初始化的代码大概长这样:
// 初始化浏览器分配器上下文 browserPath, err := "C:\Program Files \Microsoft\Edge\Application\msedge.exe" opts := append(chromedp.DefaultExecAllocatorOptions, chromedp.ExecPath, chromedp.NoFirstRun, chromedp.NoDefaultBrowserCheck, chromedp.Headless, ) allocCtx, cancel := chromedp.NewExecAllocator, opts...) defer cancel,最终的最终。
话虽然是这么说… 这段代码就像是给浏览器下达了“静音指令”, 告诉它:“别废话,干活就是了。”
第二步:模拟不同设备并截图
拿到了浏览器环境,接下来就是最关键的一步:怎么把网页“画”下来。我们不能简单地截个全屏, 主要原因是我们要模拟的是不同的设备——iPhone SE、iPad Pro、Desktop 1080p等等。这就涉及到视口的模拟,我emo了。。
这里我封装了一个函数takeScreenshotForDevice 它接收URL、宽度和高度作为参数。利用chromedp.EmulateViewport 我们可以欺骗浏览器, 他破防了。 让它以为自己正运行在不同尺寸的屏幕上。
func takeScreenshotForDevice {
var buf byte
err := chromedp.Run(ctx,
chromedp.EmulateViewport, int64),
chromedp.Navigate,
chromedp.Sleep, // 稍微留点时间让JS跑一跑
chromedp.WaitVisible,
chromedp.CaptureScreenshot,
)
if err != nil {
return nil, err
}
img, _, err := image.Decode)
if err != nil {
return nil, err
}
bounds := img.Bounds
rgba := image.NewRGBA
draw.Draw
return rgba, nil
}
图像处理与合成
拿到了所有设备的截图,这只是半成品。为了让预览图看起来像那么回事,我们需要把这些截图“塞”进真实的设备外壳里。这就好比给手机贴膜,得严丝合缝才行。
先说说我们需要创建一个足够大的画布。背景色我选了纯白,这样看起来比较干净。这里用到了imaging库,它比标准库的image提供了更多便捷的图像处理方法。
摆烂。 canvas := imaging.New
接下来就是最繁琐但也最有成就感的环节:遍历所有设备。对于每一个设备,我们都要做三件事:读取设备图片、 地道。 解码图片数据、转换为 RGBA 格式以便绘制。
再说说一步:拼贴画布
定位与绘制根据预设的布局坐标,先把刚才截取的网页内容画到底层。然后覆盖外壳再说说把设备外壳盖在最上面。 闹乌龙。 这一步必须精准,否则屏幕内容就会错位,看起来非常滑稽。
我个人认为... for _, dev := range Devices { ... // 读取设备图片 ... // 解码图片数据 ... // 转换为 RGBA 格式以便绘制 ... // 将外壳覆盖到画布的对应位置 ... }
当循环结束, 一张包含iPhone、iPad、MacBook等多设备展示的精美预览图就静静地躺在内存里了。再说说一步,自然是把这个杰作保存到磁盘上。创建文件流,调用PNG编码,大功告成,PTSD了...!
outFile := "output/preview.png" f, err := os.Create if err != nil { panic } defer f.Close if err := png.Encode; err != nil { panic } fmt.Println,拯救一下。
这个周末的小项目, 虽然代码量不算巨大,但解决了我实实在在的痛点。从一开始的一时兴起,到查文档、写代码、调Bug,再说说看着生成的预览图,那种成就感是难以言喻的。
也是没谁了。 虽然这个工具已经能满足我当下的需求, 但作为一个有追求的开发者,我心里清楚它还不够完美。比如现在的并发虽然快,但对机器内存的消耗也不小。如果一边开几十个无头浏览器实例,普通的笔记本估计得冒烟。未来或许可以考虑引入任务队列,限制并发数,做一个更优雅的调度器。

