前言
小程序canvas
有多坑,相信开发过的同学们都深有体会
每一次写使用canvas
都忍不住骂两句
鉴于此,小弟就从0开始,一步一步实现画图
功能,并且列明所有我遇到的坑
注意:本文都是基于uni开发,请注意使用
鉴于,微信官方说旧接口不再维护(旧的canvas更坑!),所以本文全部都是讲述
Canvas 2D
使用canvas 2d
<canvas type="2d" id="myCanvas" class="canvas">canvas>
注意
在以前的canvas
中,是需要填写canvas-id
的,如今已经不需要
需要添加type="2d"
这个属性
下面代码有误,应该传入宽高设置canvas
获取canvas
实例,建议封装成为一个Promise
,
const MAX_DPR = 2; const PIXEL_RATIO = DPR > MAX_DPR ? MAX_DPR : DPR; const createCanvas = (id, context) => { return new Promise((resolve) => { uni.createSelectorQuery() .select(id) .fields({ node: true, size: true }) .exec(([{ node: canvas }]) => { const ctx = canvas.getContext('2d'); canvas.width = canvas._width * PIXEL_RATIO * PIXEL_RATIO; canvas.height = canvas._height * PIXEL_RATIO * PIXEL_RATIO; ctx.scale(PIXEL_RATIO, PIXEL_RATIO); resolve({ ctx, canvas }); }); }); };const DPR = uni.getSystemInfoSync().pixelRatio;
注意
在小程序文档中,并没有传context
这个上下文,这是由于官方demo
是在根组件,而这个放在在组件中,如果想要获取DOM
元素,必须要加上上下文,否则会获取不到DOM
。当然,官方也有建议在组件中使用this.createSelectorQuery()
在上述方法中,需要设置canvas
的宽高,而为了在开发中能直接使用美术稿尺寸,所以乘了DPR
倍
再乘DPR
是为了防止最后的画出来图片模糊问题,但需要再scale
放大
当然,你也可以不设置canvas
的样式宽高,直接在这个js
方法里面进行设置
这里有一个大坑!!!DPR
不能大于2
,否则在手机上会报错!!!
开始画图
const CANVAS_HEIGHT = 970; /*白色背景*/ ctx.fillStyle = '#ffffff'; ctx.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT); /*绘制文字*/ ctx.font = '50px sans-serif'; ctx.fillStyle = '#000000'; ctx.textBaseline = 'top'; ctx.fillText('前端背锅侠', 0, 0);const CANVAS_WIDTH = 580;
注意
Canvas 2D使用
W3C
标准的Canvas
,即语法是web canvas
既然语法变了,就千万千万不要把微信小程序上的文档给搞混了!!!
文本基线是普通的字母基线,记得转回top
值,便于量美术稿高度尺寸
设置字体的时候,记得带上font-family
!!(直接封装成方法吧~)
生成图片
由于导入图片到canvas
过于简单(直接使用),在此不再阐述,直接跳到生成图片环节
new Promise((resolve, reject) => { uni.canvasToTempFilePath({ x: 0, y: 0, canvas, success: ({ tempFilePath }) => { resolve(tempFilePath); }, fail: reject }); });const canvasToPath = (canvas) =>
注意
建议把方法封装成Promise
记得传入canvas
,否则会报错!!
完整代码
const CANVAS_WIDTH = 580; const CANVAS_HEIGHT = 970; ctx.fillStyle = '#ffffff'; ctx.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT); ctx.font = '50px sans-serif'; ctx.fillStyle = '#000000'; console.log(ctx.textBaseline); ctx.textBaseline = 'top'; ctx.fillText('前端背锅侠', 0, 0); const path = await canvasToPath(canvas);const { ctx, canvas } = await createCanvas('#myCanvas', this);
注意事项
千万别以为复制了我上面的代码就完事大吉,还有坑!!
canvas 2d
不能真机调试,会报错,只能预览
当画图的时候微信开发者工具
,没有报错,又不显示画图的结果,尝试更新详情-本地设置-调试基础库
,把基础库调高一点
注意异步问题
永远不要相信微信开发者工具
,工具能画图,不代表手机也行,手机预览才是最重要的!!
在画图的时候,设置数值不建议使用小数,否则会有你意想不到的坑
微信在不断迭代更新中,我上述的一些问题,可能再后续会被微信修复掉,同学萌要稍微注意一下
假如日常开发小程序的时候,遇到canvas
的坑,可以回来看看本文
假如你遇到其他canvas
的坑,可以加我微信,继续补充,共同爬坑
本文属个人理解,如有错误,期待你的提出及交流,谢谢。