在应用开发过程中,我们会遇到各种各样的分享场景,例如邀请、拉新、分享内容等。分享链接是 Web 时代常见的分享形式,实现也相对容易。但是现在人们时间大都花在了 APP 上,所以应用之间的分享越来越重要,然而应用之间分享链接却不是那么顺利和有效果。往往受以下制约:
- 纯文字链接,依靠文字向外界传达信息,信息量小、可信度低。群里丢了一个链接进来,什么描述都没有,大多数人都不会去点。链接的描述一般也不会太长,信息不会太多。
- 分享的目标应用的外链策略。淘宝购物链接不能分享到微信、营销链接容易被微信封禁,都是受微信外链策略的影响。
- 平台分享机制限制。小程序的转发功能允许用户直接将小程序分享到联系人中,却无法分享到朋友圈。若开发者希望用户可以分享小程序到朋友圈中,通常需要生成分享海报图片,分享图片到朋友圈中。
所以 APP、H5、小程序等应用中分享功能,除了实现分享链接以外,还需要生成分享海报图片,在图片上展现更丰富的内容,一图胜千言。
如何低成本地生成内容丰富的海报图片,就是我们想要解决的问题。
常见技术方案
从生成图片的位置划分,可以将方案划分为两种:客户端生成、服务端生成。
在客户端生成图片是将图片中的元素都下载到本地,然后使用绘图 API 进行绘制,典型方案就是使用 Canvas 来绘制图片。
在服务端生成图片,又可以分为两种,一种是在服务端使用绘图库绘制,然后返回图片或图片链接给客户端;另一种是在服务端使用HTML + CSS 生成带有样式的网页,然后使用无头浏览器截图,返回图片或图片链接给客户端。
简而言之,一般会使用下面这三种方式:
- 在客户端使用 Canvas 生成图片
- 在服务器上使用网页完成样式渲染,然后截图返回给客户端
- 使用后端绘图库绘制,然后返回给客户端
下面逐一分析各种方案生成海报图片的优缺点。
客户端使用 Canvas 生成海报图片
优点:
- 渲染过程在每个客户端中完成,渲染相对独立,基本上不需要考虑并发的问题。
- Canvas 特性丰富,可以实现样式复杂的图片渲染。
缺点也很明显:
- 上手门槛高,需要灵活使用 Canvas API
- 代码可读性差,调试过程复杂。
- 代码复用程度低,每个端都需要重新编码。客户端型号众多,用户设备上的表现还可能与在开发机上的表现存在差异。兼容性太差,这是客户端渲染最大的痛点。
- 如果有远程图片,可能会因跨域,无法下载,导致绘制失败。
推荐阅读:小程序canvas绘制海报
服务端浏览器,网页截图
在服务器上使用 HTML + CSS 在无头浏览器中完成网页样式布局与内容填充,然后使用无头浏览器提供的截图 API,将生成的网页截图保存。无头浏览器一般会选用 Puppeteer
。
Puppeteer
是谷歌官方团队开发的一个 Node.js 库,它提供了一些 API 用来控制浏览器的行为,比如打开网页、模拟输入、点击按钮、屏幕截图等操作,通过这些 API 可以完成很多有趣的事情,比如本文要讲的海报渲染服务,就会用到屏幕截图功能。
这种方案的优缺点也很明显。
优点:
- 上手简单,只需要了解 HTML 、CSS 就可以
- 代码可读性高,易于调试
- 得力于HTML、CSS,表达力强。只要在网页上能实现,就可以应用到海报图片中。
- 返回给客户端的是图片链接,不用考虑兼容性。
服务端生成图片带来的最大好处是多端兼容。但这也会引入一个问题,成本高。
在后端需要运行一个 Node 服务来跑Puppeteer
控制一个浏览器,性能太低。一个4核16G内存的服务器生成图片,峰值QPS只有 10-20,在较差情况下每秒只能生成10张图片。
服务端绘图库绘制图片
在服务端中,使用绘图库,绘制图片,然后将图片保存至 CDN 中,再返回图片链接给客户端。常用编程语言都有绘图库,例如 PHP 的 GD 库。相较于控制浏览器截图,这个方案的性能更高,也具有服务端渲染的好处,但灵活性却没有使用CSS控制样式高。
优点:
- 性能高
- 服务端架构统一,开发者不用单独维护一个Node.js 服务。
- 代码可读性高
缺点:
- 复杂样式,开发时间长,需要微调。
- 自适应布局困难。
推荐阅读:PHP 使用GD库合成带二维码的海报步骤以及源码实现
上面介绍了三种生成分享海报图片的常用方案,了解了实现原理。开发者在实现这些方案时都需要进行独立的开发,维护复杂的样式代码,每增加一种海报,就需要维护一份样式代码。
海报只是业务中很小的一环,自己维护一个海报渲染服务,付出的成本与收益之间不成正比。所以我们更推荐使用第三方海报/图片渲染服务,来完成实现我们的想法。
imgrender.cn 动态图片渲染服务
Imgrender 是一个免费的图片渲染服务,通过一个API,根据配置动态渲染图片,快速生成不同内容的图片。渲染模板配置简单,特别适合拥有不同分享海报的应用,快速、动态地生成分享海报。Imgrender 支持「文本」、「图片」、「二维码」、「矩形」、「线段」五种组件,可满足绝大多数海报的渲染需求。
- 👏 免费
- 📝 API 优先
- 🛣 动态渲染,内容可动态调整
- 🖥 易于配置,方便调试
- 📱 兼容性高,渲染结果只与配置有关
- ⚡️ 快速、稳定,平均响应时间 400ms
Imgrender 只有一个核心 API,通过 API 传递海报内容,就可以动态生成不同内容的图片。海报内容完全配置化,在完成设计稿后,按照设计尺寸和位置生成配置即可。
使用服务也很简单,只需要请求 POST https://api.imgrender.net/open/v1/pics
。将下面的 curl 命令复制到终端请求一下,就可以得到渲染好的海报图片链接。
curl 命令中 Apikey 是临时的,可能会失效,你可以在 imgrender 中免费获取 API Key。
curl -X "POST" "https://api.imgrender.net/open/v1/pics" \
-H "Authorization: Apikey 183666749185461475.PLbfIpBpeMkpgbj1Tr+177Mv3Jo3wIIySyf8V5ZeDhs=" \
-H "Content-Type: application/json; charset=utf-8" \
-d '{
"width": 640,
"height": 1050,
"backgroundColor": "#d75650",
"blocks":[
{
"x": 15,
"y": 268,
"width": 610,
"height": 770,
"backgroundColor": "#fff",
"borderColor": "#fff"
}
],
"texts":[
{
"x": 320,
"y": 185,
"text": "Davinci Li",
"font": "jiangxizhuokai",
"fontSize": 22,
"color": "#fff",
"width": 320,
"textAlign": "center"
},
{
"x": 320,
"y": 220,
"text": "邀请你来参加抽奖",
"font": "jiangxizhuokai",
"fontSize": 22,
"color": "#fff",
"width": 320,
"textAlign": "center"
},
{
"x": 30,
"y": 640,
"text": "奖品: 本田-CB650R 摩托车",
"font": "jiangxizhuokai",
"fontSize": 22,
"color": "#000",
"width": 580,
"textAlign": "left"
},
{
"x": 30,
"y": 676,
"text": "01 月 31 日 18:00 自动开奖",
"font": "jiangxizhuokai",
"fontSize": 18,
"color": "#9a9a9a",
"width": 580,
"textAlign": "left"
},
{
"x": 320,
"y": 960,
"text": "长按识别二维码,参与抽奖",
"font": "jiangxizhuokai",
"fontSize": 22,
"color": "#9a9a9a",
"width": 580,
"textAlign": "center"
}
],
"lines":[
{
"startX": 30,
"startY": 696,
"endX": 610,
"endY": 696,
"width": 1,
"color": "#E1E1E1",
"zIndex": 1
}
],
"images":[
{
"x": 248,
"y": 25,
"width": 120,
"height": 120,
"url": "https://img-chengxiaoli-1253325493.cos.ap-beijing.myqcloud.com/bikers_327390-13.jpg",
"borderRadius": 60,
"zIndex": 1
},
{
"x": 108,
"y": 285,
"width": 400,
"height": 300,
"url": "https://img-chengxiaoli-1253325493.cos.ap-beijing.myqcloud.com/cb650R.jpeg",
"zIndex": 1
}
],
"qrcodes":[
{
"x": 208,
"y": 726,
"size": 200,
"content": "http://weixin.qq.com/r/yRzk-JbEbMsTrdKf90nb",
"foregroundColor": "#000",
"backgroundColor": "#fff",
"zIndex": 1
}
]
}'
请求返回内容:
{
"code":0,
"message":"OK",
"data":"https://davinci.imgrender.cn/c3037d467c163bd903760f96a34f3bcd.jpg?sign=1616722062-plQZQ4xtth9tEthx-0-2a98ba98e5fd44cc6dffb3aec6d3398f"
}
data
字段就是动态渲染好的海报图片链接,下载或打开链接就可保存图片。查看详细使用方法。
imgrender.net 推荐按以下最佳实践来使用海报生成服务:
所有的海报配置全都管理在服务端中,服务端只需要提供一个 API 给客户端。客户端通过这个 API 请求不同的分享图,服务端接收到请求后,先检查服务端是否缓存分享图。若没有缓存图片,则使用海报配置去 imgrender 动态生成海报,然后将生成的图片链接返回给客户端,供用户下载保存。
使用 imgrender 动态渲染海报,在满足需求的同时,可以大幅度降低开发成本,提高多端兼容性。无论是开发小程序海报,还是原生应用中的海报,一套代码即可搞定。
原文链接:https://mp.weixin.qq.com/s/6ss1D4wneNDuhUfplualQQ
关键词:海报图、海报分享图、海报生成、图片生成、小程序海报生成
如果繁琐的参数(尤其x,y坐标)有一套匹配的可视化工具来生成,可能推广效果更好
受楼主启发,我用阿里的OSS里面的图片处理服务可以达到想要的目的。具体参考:
https://help.aliyun.com/document_detail/44957.html
后端服务的想法挺好的,但是这个服务真的可以支持商用吗?
需要你的API_KEY
如果传了oss上的图片,就会提示:Image download failed
看了还是不会