你一定见过很多制作头像的小程序,无论是国庆的红旗,圣诞的帽子,还是疫情的口罩,都可以用小程序生成应景的头像,那么具体的代码是怎么实现的呢?前些天帮别人做了一个生成姓氏头像的功能,里面的实现原理基本一致,都是通过Canvas实现,以生成姓氏头像为例,记录一下小程序的Canvas如何使用. (小程序的文档就是依托答辩😒)
小程序Canvs
1.canvas的标签
如果你想使用它的话,要先在wxml写上canvas标签,这里有坑,注意你的写法,如果你上网copy的代码,绝大部分是老版的canvas.
老版的canvas,部分api已经失效,新版的文档写了等于没写.
//旧版 写法
<canvas canvas-id="myCanvas" />
//新版 写法
<canvas id="myCanvas" type="2d" />
新版的必须声明 type="2d"
//区别不是很大,如果你在网上找代码 一定要使用对应版本的api
2.获取canvas对象及上下文内容
//旧版获取canvas上下文
const context = wx.createCanvasContext('myCanvas')
// 新版获取canvas及上下文
wx.createSelectorQuery() //此方法等于获取页面所有节点
.select('#myCanvas') //类似原生JS的选择器,这里根据id
.fields({ node: true, size: true })//获取到的节点属性配置,node是否返回实例,size是否返回尺寸大小尺寸
.exec((res)=>{ //获取之后的回调
// Canvas 对象
const canvas = res[0].node
// 渲染上下文
const ctx = canvas.getContext('2d')
})
3.初始化canvas画布
wx.createSelectorQuery()
.select('#myCanvas')
.fields({ node: true, size: true })
.exec((res)=>{
// Canvas 对象
const canvas = res[0].node
// 渲染上下文
const ctx = canvas.getContext('2d')
// Canvas 画布的实际绘制宽高
const width = res[0].width
const height = res[0].height
// 初始化画布大小
const dpr = wx.getWindowInfo().pixelRatio//获取屏幕比例,用来解决渲染画布模糊的问题
canvas.width = width * dpr
canvas.height = height * dpr
ctx.scale(dpr, dpr)
// 用来解决画布里面东西能够自适应,不同屏幕不同尺寸 375不行的话用750
const ratio = wx.getSystemInfoSync()?.windowWidth / 375;
})
4.开始绘制canvas内容 (开始接入业务,可按照自己需求进行)
wx.createSelectorQuery()
.select('#myCanvas')
.fields({ node: true, size: true })
.exec((res)=>{
//...
//省略了步骤3的代码,使用时,请自己补全!!!!慎记!!!
//...
//清除画布内容
//前两个参数 可以理解为 要清除的起点 x y坐标
//后两位参数 是你要选择的区域大小
//以下为例 在画布的 0 0 起点清空高宽与画布本身相等的区域,等于全部清空
ctx.clearRect(0, 0, width, height)
//因为我是生成姓氏头像,所以画布的底图是提前有的
//可以是获取用户 可以走接口 图片地址用Https!!!!
//创建图片对象
const bg = canvas.createImage()
//底图地址
bg.src = 'https://gitee.com/ouchFF/blog_img/raw/master/img/bg.jpg'
bg.onload = () => { //图片加载完毕
//第一个参数是图片对象 其他参数与清空画布类似
ctx.drawImage(bg, 0, 0, width, height) //绘制图片
}
})
写到这一步,不出意外已经可以看见我们绘制的底图了.
5.生成姓氏,并绘制到canvas画布上
//这里写生成姓氏的方法 通过点击页面按钮触发
//这里的姓氏 本质是一张图片 因为生成的姓氏是带字体的
//设置自定义字体我搞了好久也没成功,希望有人能给我解答
//正常是 用户写一个姓氏,调用接口,后端返回一个姓氏的png图片地址
//我这里没有接口,所以直接用我准备好的图片
selectText() { //点击按钮触发
//第三步的时候 我已经将 canva相关东西存入data里了 这里直接用
const _this = this.data
const bg = _this.canvas.createImage() //创建图片对象
//假装这是后端返回的一个姓氏图片地址
bg.src = 'https://gitee.com/ouchFF/blog_img/raw/master/img/shuai.png'
bg.onload = () => {
_this.ctx.drawImage(bg, 150 * _this.ratio, 150 * _this.ratio, 40 * _this.ratio, 40 * _this.ratio) //绘制图片
}
//这里每个值我都乘了一个ratio 这是因为api本身默认单位是px
//在不同屏幕下 可能位置会偏移 为了实现像rpx那样能自适应,需要乘以一个系数
//这个系数 是在第三步中 计算的
},
点击按钮后效果如下图 会看见叠加了一张姓氏图
假设你并没有字体要求,只是单纯的想添加文字,那么也可以按以下写法
//向画布中添加 文字
selectText2() {
const { ctx, canvas, ratio,dpr } = this.data
// 设置文字样式 这代码是我想设置自定义字体的 并没有生效,可以忽略
//除了字体样式 其他设置是生效的
ctx.font = `normal ${50*ratio}px 仓耳渔阳体`; //设置字体
ctx.font = `normal ${50*ratio}px font`; //设置字体
//添加文字 第一个参数是文字内容
//其他参数是起始点x y (这里起始点可能有问题 可以自己看看文档)
ctx.fillText(this.data.text, 100*ratio, 100*ratio); //绘制文字
},
6.将生成的canvas内容保存到我们自己的手机上
save() {
//同样 新老版本有差异 我这是新版的保存
wx.canvasToTempFilePath({
canvas: this.data.canvas,
success: (res) => {
wx.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success(res) {
wx.showToast({
title: "保存成功,请在相册中查看",
});
},
});
},
fail(error) {
return reject(error);
},
});
},
至此,一个简单的生成头像功能就完成了.有需要此案例源码的,可以私信我~~