Skip to content

Instantly share code, notes, and snippets.

@semlinker
Last active October 12, 2023 09:24
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save semlinker/6a826648a8ba6cffe70233a2b401a5a9 to your computer and use it in GitHub Desktop.
Save semlinker/6a826648a8ba6cffe70233a2b401a5a9 to your computer and use it in GitHub Desktop.
/**
* 说明信息
* 1.目录结构:
* ├── avatar.jpg
* ├── qrcode.jpg
* ├── share-image.js
* ├── simhei.ttf
* └── template.jpg
* 2.备注:若出现资源路径异常时,则使用path.join(__dirname, "./simhei.ttf")的方式进行资源加载
* 3.示例:
* share.genShareImage({
* backgroudPath: "template.jpg",
* avatarPath: "avatar.jpg",
* qrcodePath: "qrcode.jpg",
* userName: "semlinker",
* words: 2888,
* likes: 188,
* outFilePath: path.join(__dirname, `public/images/${+new Date()}.png`)
* })
*/
const sharp = require("sharp");
const TextToSVG = require("text-to-svg");
const path = require("path");
// 加载字体文件
const textToSVG = TextToSVG.loadSync(path.join(__dirname, "./simhei.ttf"));
// 创建圆形SVG,用于实现头像裁剪
const roundedCorners = new Buffer(
'<svg><circle r="90" cx="90" cy="90"/></svg>'
);
// 设置SVG文本元素相关参数
const attributes = { fill: "white" };
const svgOptions = {
x: 0,
y: 0,
fontSize: 32,
anchor: "top",
attributes: attributes
};
/**
* 使用文本生成SVG
* @param {*} text
* @param {*} options
*/
function textToSVGFn(text, options = svgOptions) {
return textToSVG.getSVG(text, options);
}
/**
* 图层叠加生成分享图片
* @param {*} options
*
*/
async function genShareImage(options) {
const { backgroudPath, avatarPath, qrcodePath,
userName, words, likes, outFilePath
} = options;
// 背景图片
const backgroudBuffer = sharp(path.join(__dirname, backgroudPath)).toBuffer({
resolveWithObject: true
});
const backgroundImageInfo = await backgroudBuffer;
// 头像图片
const avatarBuffer = await genCircleAvatar(path.join(__dirname, avatarPath));
// 二维码图片
const qrCodeBuffer = await sharp(path.join(__dirname, qrcodePath))
.resize(180)
.toBuffer({
resolveWithObject: true
});
// 用户名
const userNameSVG = textToSVGFn(userName);
// 用户数据
const userDataSVG = textToSVGFn(`写了${words}个字 收获${likes}个赞`);
const userNameBuffer = await sharp(new Buffer(userNameSVG)).toBuffer({
resolveWithObject: true
});
const userDataBuffer = await sharp(new Buffer(userDataSVG)).toBuffer({
resolveWithObject: true
});
const buffers = [avatarBuffer, qrCodeBuffer, userNameBuffer, userDataBuffer];
// 图层叠加参数列表
const overlayOptions = [
{ top: 150, left: 230 },
{ top: 861, left: 227 },
{
top: 365,
left: (backgroundImageInfo.info.width - userNameBuffer.info.width) / 2
},
{
top: 435,
left: (backgroundImageInfo.info.width - userDataBuffer.info.width) / 2
}
];
// 组合多个图层:图片+文字图层
return buffers
.reduce((input, overlay, index) => {
return input.then(result => {
console.dir(overlay.info);
return sharp(result.data)
.overlayWith(overlay.data, overlayOptions[index])
.toBuffer({ resolveWithObject: true });
});
}, backgroudBuffer)
.then((data) => {
return sharp(data.data).toFile(outFilePath);
}).catch(error => {
throw new Error('Generate Share Image Failed.');
});
}
/**
* 生成圆形的头像
* @param {*} avatarPath 头像路径
*/
function genCircleAvatar(avatarPath) {
return sharp(avatarPath)
.resize(180, 180)
.overlayWith(roundedCorners, { cutout: true })
.png()
.toBuffer({
resolveWithObject: true
});
}
module.exports = {
genShareImage
};
@daileimail
Copy link

nice

@xuyixuancheng
Copy link

请问有遇到windows上可以显示文字水印,mac上不出现的情况吗

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment