在平时的项目中,我们经常会有生成活动营销海报的需求,一般是有一张海报的背景图,然后动态获取用户头像,将头像裁剪成圆形,动态获取用户昵称,动态生成用户专属的二维码,最后将用户的圆形头像,昵称和二维码合并到背景图上,就生成了该用户专属的分享海报。上面提到的几点,可能任何一点都会让你找半天资料,最后还不一定有效,耽误项目进度,影响自己心情,所以这里分享一下最近的一些经验,让你看完这篇文章,就可以在 node.js 的环境中完美的实现这个需求。
首先,概括的来看这个需求,我们需要将一些图像附着在一张背景图上面,合成一张新的图片。通过网上查找资料,发现主要有这么几个库或者包可以实现图片合成的功能:GraphicsMagic、images、sharp。
我们先来把用户的方形头像转化为圆形头像。如果是在前端页面展示,那么直接给 img 标签设置 border-radius 样式就可以了。但如果是在 node.js 的服务端,有一张正方形的头像图片,需要生成一个圆形的头像,应该怎么做呢?
首先,如果我们获取的用户头像是一张网络图片,例如用户的微信头像,我们先把方形头像保存成本地图片。我们进行一次 GET 请求,url 就写头像地址,网络请求返回给我们的就是图片数据,然后我们把图片数据写入到本地文件就可以了。网络请求使用的是 request-promise 包。要注意的是,在请求中,要注明编码 encoding 为 null 或者 “binary”,这样获取到的数据保存成图片后,才可以正常打开,不然获取的数据保存后的图片是无法打开的。
import rp from 'request-promise'
import fs from 'fs'const options = {method: 'GET',uri: '', // 头像地址encoding: 'binary' // 或者也可以是 null
}
rp(options).then(response => {fs.writeFileSync('avatar.png', response, 'binary')
})
假设我们要保存的头像文件为 avatar.png,调用 fs 的 writeFileSync 方法同步的将图片数据写入到文件中。注意第三个参数,也要写 ‘binary’。然后你就能发现,头像已经保存到了本地,并且可以正常打开,下面我们将方形头像转化为原型头像。
头像的转化用到了 sharp,所以要先在项目中使用 npm 安装 sharp 包。然后我们创建一个 Buffer 缓存区,这个 Buffer 缓存区读取的是一个 svg,这个 svg 里面是一个矩形(rect),因为我们最终想把原型头像的大小调整为 100*100,所以 svg 里面 rect 的 width 和 height 都是 100,rx 和 ry 用来表示圆角,把圆角设置为宽高的一半,就是一个圆形(其实是一个圆角矩形)。对 Buffer 和 svg 不太了解的话,可以先去专门去了解一下。然后我们使用 sharp 的 composite 方法,将圆形的 svg 和方形的头像进行合成,就能得到一个圆形的头像。注意 blend 的类型有很多,自己可以分别尝试一下,使用 dest-in 可以实现需要的这种效果。
import sharp from 'sharp'const roundedCorners = Buffer.from(
'<svg><rect x="0" y="0" width="100" height="100" rx="50" ry="50"/></svg>'
)
sharp('avatar.png')
.resize(100,100)
posite([{input:roundedCorners, blend: 'dest-in'}])
.png()
.toFile('circleAvatar.png')
下面我们将二维码图片保存到本地,如果你得到的已经是一个二维码的图片,那你可以像上面那样,进行一次 GET 请求,然后将请求的结果直接保存成本地图片就可以。如果你得到的是一个链接,才准备将这个链接生成一个二维码,那你可以使用 qrcode 这个包。这个包用来生成二维码还是很好用的,可自由配置很多东西。
import QRCode from 'qrcodeFile('qrcode.png','',{margin: 2,width: 240})
下面我们将用户昵称转化为本地图片。我们获取的用户昵称是一个字符串,要先使用 text-to-svg 这个包,把它转为 svg。可以设置字体,字体大小,颜色等很多参数。然后再通过 sharp 将 svg 文件转为 png 文件,因为我们最终合成海报时需要的是图片文件。
import TextToSVG from 'text-to-svg'
import sharp from 'sharp'const textToSVG = TextToSVG.loadSync()
const attributes = {fill: 'white'};
const options = {x: 0, y: 0, fontSize: 40, anchor: 'top', attributes: attributes};
const svg = SVG('mofiter',options)
fs.writeFileSync('nickname.svg',svg)
await sharp('nickname.svg').png().toFile('nickname.png')
当我们得到了圆形头像图片 circleAvatar.png,二维码图片 qrcode.png,昵称图片 nickname.png,我们就可以使用 sharp 的 composite 方法将这些图片合并到海报背景图片 background.png 上面,生成个人专属的海报。要合并的图片位于背景上的什么位置,可以通过 left 和 top 指定。
sharp('background.png')posite([{input:'circleAvatar.png',left:65,top:80},{input:'nickname.png',left:180,top:80},{input:'qrcode.png',left:760,top:1620}]).png().toFile('poster.png')
通过上面的这些步骤,就可以生成一张完整的海报啦,在真正用到的时候,要注意 ES6 的语法,还有同步和异步的问题,希望本文可以对你有所帮助。
本文发布于:2024-02-04 23:39:11,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170719006460807.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |