前言:在朋友圈看到国庆头像,突发奇想自己能不能做个工具来生成头像,然后想到了小程序
1. -创建小程序
然后我们得到一个初始化的小程序
2. -整理文件夹逻辑
这里我们把这些原始文件都清空,得到如下文件夹
3. -编写页面样式
开始写页面,得到如下主页面
配色参考的这个网站:webgradients.com/
接下来是内部样式
由于小程序对代码包的大小有限制,所以我们把头像样式图片放在云存储里面,优化包体积
然后再进入此页面时先从云存储空间存储到本地缓存
/* 图片下载到本地 */
downloadImg () {
wx.showLoading({
title: "加载中",
})
// 云存储图片地址数组
const imgUrls = [
'cloud://xxx/image/cn-1.png',
'cloud://xxx/image/cn-11.png',
'cloud://xxx/image/cn-9.png',
'cloud://xxx/image/cn-3.png',
'cloud://xxx/image/cn-4.png',
'cloud://xxx/image/cn-5.png',
'cloud://xxx/image/cn-6.png',
'cloud://xxx/image/cn-7.png',
]
wx.cloud.getTempFileURL({
fileList: imgUrls
})
.then(({ fileList }) => {
const imgList = []
fileList.forEach((item, index) => {
const obj = {
url: item.tempFileURL,
name: 'cn' + index
}
imgList.push(obj)
})
// 赋值,初始化
this.setData({
tagList: imgList,
})
wx.hideLoading()
}).catch(err => {
wx.hideLoading()
console.log(err)
})
},
onLoad () {
this.downloadImg()
}
4. -编写上传图片和canvas绘制头像逻辑
/* 上传图片 */
uploadHandle () {
const _this = this
wx.chooseMedia({
count: 1, // 选择的最大数量
mediaType: ['image'], // 选择的文件类型
sourceType: ['album', 'camera'], // 可从相册选择或拍摄
camera: 'back', // 默认后置摄像头
success (res) { // 选择成功回调
_this.setData({
backUrl: res.tempFiles[0].tempFilePath // 所选文件的临时路径
})
}
})
}
/* 绘制头像 */
draw () {
function getImageInfo (url) {
return new Promise((resolve, reject) => {
wx.getImageInfo({
src: url,
success: resolve,
fail: reject,
})
})
}
const { backUrl, tagUrl } = this.properties
// 获取背景(头像)图片信息
const backgroundPromise = getImageInfo(backUrl)
// 获取合成元素图片信息 (tag)
const tagPromise = getImageInfo(tagUrl)
Promise.all([tagPromise, backgroundPromise])
.then(([tag, background]) => {
// 获取canvas上下文
// createSelectorQuery默认初始时,选择器仅选取页面范围的节点,不会选取任何自定义组件中的节点
// 需用in(this)将选择器的选取范围更改为自定义组件 component 内
const query = wx.createSelectorQuery().in(this)
query.select('#canvas')
.fields({ node: true, size: true })
.exec((res) => {
const canvas = res[0].node
this.setData({
canvasObj: canvas
})
// 设备的缩放比
const pixelRatio = this.data.pixelRatio
// 设置canvas宽高
const canvasWidth = res[0].width * pixelRatio
const canvasHeight = res[0].height * pixelRatio
canvas.width = canvasWidth
canvas.height = canvasHeight
const ctx = canvas.getContext('2d')
// 绘制背景,填充满整个canvas画布
const backImg = canvas.createImage()
backImg.src = background.path
backImg.onload = () => {
console.log('背景')
ctx.drawImage(
backImg,
0,
0,
canvasWidth,
canvasHeight
)
// 头像图片绘制完成后再绘制tag
// 否则会出现tag被头像覆盖的情况
const tagImg = canvas.createImage()
tagImg.src = tag.path
tagImg.onload = function () {
console.log('tag')
ctx.drawImage(
tagImg,
0,
0,
canvasWidth,
canvasWidth
)
}
tagImg.onerror = function () {
wx.showToast({
title: '图片加载失败,请重试',
icon: 'error',
duration: 2000
})
}
}
})
})
}
5. -保存头像逻辑
/* 保存到相册 */
saveToPhone () {
const _this = this
wx.showLoading({
title: '保存中...',
})
wx.canvasToTempFilePath({
x: 0,
y: 0,
canvas: _this.data.canvasObj,
success: function (res) {
wx.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success (res) {
wx.hideLoading()
wx.showToast({
title: '已保存到相册',
icon: 'success',
duration: 2000
})
// 保存成功之后关闭弹窗
_this.closeDialog()
}
})
},
fail: function (res) {
wx.showToast({
title: '保存失败请重试',
icon: 'error',
duration: 2000
})
}
});
}
6. -最后看下成品
成品如下:
感兴趣的同学可以体验下Toolkit Pro