国庆来临,你们的节日头像换好了吗?最近“渐变国旗头像”火了,今天就为大家分享一下自己写的一个生成国庆头像的小程序。
不废话,先上图。
功能分出两个部分,第一个是渐变国旗,可以通过下面的参数调整生成的小程序。第二种就是常用的使用背景图和头像贴图。
下面小程序码直接预览效果。
渐变国旗
网上很多案例都是使用已经处理的国旗背景图贴在头像上方,来是现实生成。但我想有没有方法可以调整渐变大小、五角星大小来生成背景图呢,而不是使用固定的背景图。开始我想的是使用完善的国旗背景,canvas能不能像ps那样加个蒙版,再拉个渐变实现(这个肯定是能显示的,canvas是可以操作像素级),但是网上搜索了半天也没有找到类似的案例。
后来是GitHub上找到一个另一种方法是现实的,就是这个项目查看这里,这个项目的实现方式是,先把国旗五角星部分剪成单独图片,而国旗的背景色通过canvas绘制,通过这样就可以显示调整生成渐变效果。
直接贴上渐变国旗代码,params为滑块的值,先把用户头像绘制到canvas上,大小覆盖这个canvas。然后这里list是多种渐变模式,0是圆形渐变,1是从左到右的线性渐变,2是从左上角到右下角的线性渐变。
这里大家可以自己根据想法扩展。然后绘制一个矩形,矩形的填充颜色使用上面生成的渐变。最后把五角星贴到最上面,效果就出来啦。
async generate1() {
const {
ctx,
params: { starSize, gradientPostion, gradientSzie, gradientSection }
} = this;
if (this.avatar) {
const avatar = await this.loadImage(this.avatar);
ctx.drawImage(avatar, 0, 0, size, size);
}
const list = {
0: () => {
return ctx.createRadialGradient(
0,
gradientPostion.value,
0,
0,
gradientPostion.value + 20,
gradientSzie.value * (1.414 / 1.5)
);
},
1: () => {
return ctx.createLinearGradient(
0,
size / 2,
gradientSzie.value,
size / 2
);
},
2: () => {
return ctx.createLinearGradient(
0,
0,
gradientSzie.value,
gradientSzie.value
);
}
};
let Gradient = list[this.imageIndex]();
Gradient.addColorStop(0, "#d80203");
Gradient.addColorStop(gradientSection.value / 10, "rgba(216,2,3,0.8)");
Gradient.addColorStop(1, "rgba(255, 255, 255, 0)");
ctx.fillStyle = Gradient;
ctx.fillRect(0, 0, size, size);
const image = this.startImage;
ctx.drawImage(
image,
0,
0,
image.width,
image.height,
size * 0.04,
size * 0.04,
starSize.value * (image.width / image.height),
starSize.value
);
},
loadImage(url) {
return new Promise((resolve, reject) => {
const image = this.canvas.createImage();
image.onload = () => resolve(image);
image.onerror = reject;
image.src = url;
});
}
因为参数变动就重新生成,如果每次清空画布在小程序中会有闪的一瞬间不好看,然而因为每次绘制都会覆盖这个画布,所以直接在保存的时候清空画布重新绘制一边,就可以提升参数变动预览的效果。
async onSaveImage() {
const { canvas, ctx } = this;
ctx.clearRect(0, 0, size, size);
await this.generate();
uni.canvasToTempFilePath({
canvas,
success: res => {
const tempFilePath = res.tempFilePath;
uni.saveImageToPhotosAlbum({
filePath: tempFilePath,
success: () => {
uni.showToast({
title: "保存相册成功",
icon: "success"
});
},
fail: e => {
if (e.errMsg !== "saveImageToPhotosAlbum:fail auth deny") return;
uni.showModal({
title: "温馨提示",
content: "请选开启添加到相册权限",
success: uni.openSetting
});
}
});
}
});
},
背景图与头像贴图
一样先上代码。这种就很简单了,就是把背景图先绘制在画布上,背景图是中间与部分是透明的,再把头像绘制在画布上,这样就完成了贴图,这种主要需要的是背景图素材。
当然大家也可以扩展,例如在某个位置加文字,例如显示很火的显示姓氏的头像,或者小挂坠修饰等等。这里就看大家的想法啦。
async generate2() {
const { ctx } = this;
const avatar = await this.loadImage(this.avatar);
ctx.drawImage(avatar, 0, 0, size, size);
const image = await this.loadImage(this.image);
ctx.drawImage(image, 0, 0, size, size);
},
其他
项目代码已上传gitee,项目地址:avatar: 头像生成微信小程序 (gitee.com)
最后就大家国庆吃好,玩好,加班好!!!哈哈