最近本人在开发一个新项目的时候,注意到官方在2.9.0开始支持了一个canvas 2D的新API,同时对webGL上支持也有了很大的改进,相信很多人用canvas的组件做一些分享海报,战绩和新闻帖功能。
这里是新的引入方式。
官方文档地址:
https://developers.weixin.qq.com/miniprogram/dev/component/canvas.html
那么新的canvas2D API有啥好处呢?
- 原本的API微信有做一定的修改,现在全面支持源生H5 JS的写法,迁移H5的老代码变成更加容易,学习成本更低
- 修复了一些诡异的BUG,例如原本在IOS早期版本写法顺序会导致clip()图片裁切失效等~
- 性能上的优化和提升,复杂动画上帧数明显
举例写法上的一些改变:
1、设置font的写法:
//原本(传值的写法)
ctx.setFontSize(20);
ctx.fillText('MINA', 100, 100)
ctx.draw()
//现在(和源生H5写法一致,赋值)
ctx.font = "16px";
ctx.fillStyle = 'blue'; //可以直接写颜色,原本的不支持
//不需要 ctx.draw()
2、获取并添加图片写法:
//原本
//使用的是 wx.getImageInfo的方法
wx.getImageInfo({
src: mainImg,//服务器返回的图片地址
success: function (res) {
console.log(res);
ctx.drawImage(res.path, 0, 0);
ctx.draw(true);
},
fail: function (res) {
//失败回调
}
});
//现在
//可以直接img.onload调用
const headerImg = canvas.createImage();
headerImg.src = headImage;//微信请求返回头像
headerImg.onload = () => {
ctx.save();
ctx.beginPath()//开始创建一个路径
ctx.arc(38, 288, 18, 0, 2 * Math.PI, false)//画一个圆形裁剪区域
ctx.clip()//裁剪
ctx.drawImage(headerImg,0,0);
ctx.closePath();
ctx.restore();
}
3、将canvas生成虚拟地址便于下载(重点):
由于官方文档没有写清楚,误导了挺多人的。这里canvas对象必须通过选择器获取,并获得对应的node节点。
async saveImg() {
let self = this;
//这里是重点 新版本的type 2d 获取方法
const query = wx.createSelectorQuery();
const canvasObj = await new Promise((resolve, reject) => {
query.select('#posterCanvas')
.fields({ node: true, size: true })
.exec(async (res) => {
resolve(res[0].node);
})
});
console.log(canvasObj);
wx.canvasToTempFilePath({
//fileType: 'jpg',
//canvasId: 'posterCanvas', //之前的写法
canvas: canvasObj, //现在的写法
success: (res) => {
console.log(res);
self.setData({ canClose: true });
//保存图片
wx.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: function (data) {
wx.showToast({
title: '已保存到相册',
icon: 'success',
duration: 2000
})
// setTimeout(() => {
// self.setData({show: false})
// }, 6000);
},
fail: function (err) {
console.log(err);
if (err.errMsg === "saveImageToPhotosAlbum:fail auth deny") {
console.log("当初用户拒绝,再次发起授权")
} else {
util.showToast("请截屏保存分享");
}
},
complete(res) {
wx.hideLoading();
console.log(res);
}
})
},
fail(res) {
console.log(res);
}
}, this)
},
分享个canvas海报的代码片段:
片段名: PoCf4emw7TgE
片段link:
https://developers.weixin.qq.com/s/PoCf4emw7TgE
总结,相对之前还要看官方文档的canvas自定义API,现在写起来更加的方便,老代码迁移起来得心应手,只要你之前会canvas,那么各种效果和动画,拿来就怼,没什么大问题~
一些奇怪的问题(注意!!!)
- canvas 2d 目前(2020年4月3日)还不支持真机调试,会报错!!!
- IDE工具 1.02.2003190 直接保存新版本canvas的API图片是打不开的,但是直接用手机保存在相册是没问题的,请更新到1.02.2003250 最新版即可解决~
- 一些老款手机用新的API保存图片会有报错问题,如华为NOTE10,请更新系统到能支持的最新,且微信也是,即可解决~
- 部分Android设备诡异的闪退和报错
这种有可能是代码写法的问题,比如:
//缺省写法 会导致部分Android机器 闪退
ctx.font = "bold 16px";
ctx.fillStyle = "#000"
//在canvas 2D的写法中,所以写法必须规范且完整
ctx.font = "normal bold 12px sans-serif";
ctx.fillStyle = '#707070';
所以在canvas 2D 的环境,所以写法必须原始且规范,不能用缺省写法,不然就会有诡异的闪退/报错。
后续:官方在7.0.13的Android版本已修复。
https://developers.weixin.qq.com/community/develop/doc/00088c13e1437890692afd8d85ec00
canvas动画闪退怎么解决啊?
另外补充一个安卓闪退的情况:
ctx.font = "normal bold 12px sans-serif";
这里面的字体如果设置比较特殊的(或者说在手机上没有这个字体,具体不太确定),如 PingFangSC-Regular、PingFang SC,也会在安卓手机闪退。
我对比了一下我的写法跟您帖子里的写法,唯一的区别就是我的代码中字体大小有个 rpx 转 px,不确定是不是由于转换的结果有小数之类的导致的问题。
ctx.font = 'normal bold 36px sans-serif';
真机粗体不生效有解决办法吗?模拟器显示正常,但是在真机上目测只有数字生效了。
OPPO R11,写了个ctx.font = "12px 微软雅黑",闪退了,忘了大佬这篇文章提醒了,已剁手惩戒/(ㄒoㄒ)/~~
剪裁圆形 对png格式的图不生效么?
官方编辑器v1.02.1911180,保存图片失败
第一点:
经测试仅加上width,height是不行,在ios使用wx.canvasToTempFilePath保存会变形,为了防止出现,只能将x,y,width,height,destWidth,destHeight全部设置!
// ==============================
第二点:
const canvas = res[0].node;
const ctx = canvas.getContext("2d");
const dpr = uni.getSystemInfoSync().pixelRatio;
canvas.width = Math.ceil(res[0].width * dpr);
canvas.height = Math.ceil(res[0].height * dpr);
ctx.resetTransform(); // 强烈建议在scale前加上这句(如果在onShow上生成海报必须要)
ctx.scale(dpr, dpr);
ctx.save();
太强了
问下,在第二点中,新的写法下载图片是不是不再受download域名限制了?
很多接口是很不错,但是有时考虑到一些用户微信没有升级。其它有一些接口是用不到。我已经修改到烦燥了!最后所有海报后台生成。暂不考虑前端生成
小程序的canvas的坑目前还是填不完的状态。楼主这代码片段有兴趣测试下,是生成失败的
点赞,大佬