概述
微信小程序的 Canvas 实在太难用,这里记录一些场景经验,提高认识。
画图的尺寸问题
在页面声明一个 canvas
<canvas id="previewCanvas" c type="2d" style=" {{canvasWidth}}px; height: {{canvasHeight}}px;"> </canvas>
封装一个画图片到 canvas 的代码
// {canvasId, width, height, canvasWidth, canvasHeight, path, success} drawImageToCanvas: function (config) { const query = wx.createSelectorQuery(); query.select(config.canvasId).fields({ node: true, size: true }).exec(e1 => { console.log('图像处理', config.canvasId, 'wx.createSelectorQuery', e1); const canvas = e1[0].node; const ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, e1[0].width, e1[0].height); ctx.mozImageSmoothingEnabled = false; ctx.webkitImageSmoothingEnabled = false; ctx.msImageSmoothingEnabled = false; ctx.imageSmoothingEnabled = false; // 必须设置为 canvas 初始化的大小,否则图片会被拉伸 // 注意,在 html 设置的 width、height 是显示大小,这里设置的是画图大小 // 如果这里的尺寸比 html 的小,就会放大;否则缩小 canvas.width = config.canvasWidth; canvas.height = config.canvasHeight; if (config.backgroundHex) { ctx.fillStyle = config.backgroundHex; ctx.fillRect(0, 0, config.width, config.height); } // 如果有图片,才画图 if (config.path) { const img = canvas.createImage(); img.onload = (e2) => { console.log("图像处理", config.canvasId, 'img.onload', e2); // 默认把图片全部像素画在目标尺寸上 ctx.drawImage(img, 0, 0, config.width, config.height); if (config.success) config.success(canvas); }; img.src = config.path; } else { if (config.success) config.success(canvas); } });
测试用例:
已知页面声明的 canvas 的 style 长宽都是300;图片的长宽是:602x397。
目前已知的长宽包括了:
- 界面长宽:界面 html 的 style 声明的长宽
- 代码长宽:代码对 canvas 设置的长宽
- 图片尺寸:drawImage 的长宽
测试1:代码长宽=界面长宽,图片尺寸=图片尺寸
onLoad: function (options) { var that = this; var url = "cloud://wxss-brick-0f77b1.7778-wxss-brick-0f77b1-1257336119/images/image1.jpeg"; wx.getImageInfo({ src: url, success: function (e2) { console.log('图像处理', 'getImageInfo', e2); that.drawImageToCanvas({ canvasId: '#previewCanvas', e2.width, height: e2.height, canvasWidth: 300, canvasHeight: 300, path: e2.path, success: function () {}, }); }, }); },
结论:图片没有压缩拉伸,超出了界面显示范围。
测试2:代码长宽=图片尺寸,图片尺寸=图片尺寸
onLoad: function (options) { var that = this; var url = "cloud://wxss-brick-0f77b1.7778-wxss-brick-0f77b1-1257336119/images/image1.jpeg"; wx.getImageInfo({ src: url, success: function (e2) { console.log('图像处理', 'getImageInfo', e2); that.drawImageToCanvas({ canvasId: '#previewCanvas', e2.width, height: e2.height, canvasWidth: e2.width, canvasHeight: e2.height, path: e2.path, success: function () {}, }); }, }); },
结论:图片填满了整个 canvas,但是被拉伸了。页面的尺寸决定了图片是否拉伸。
测试3:代码长宽=图片尺寸,图片尺寸=界面长宽
onLoad: function (options) { var that = this; var url = "cloud://wxss-brick-0f77b1.7778-wxss-brick-0f77b1-1257336119/images/image1.jpeg"; wx.getImageInfo({ src: url, success: function (e2) { console.log('图像处理', 'getImageInfo', e2); that.drawImageToCanvas({ canvasId: '#previewCanvas', 300, height: 300, canvasWidth: e2.width, canvasHeight: e2.height, path: e2.path, success: function () {}, }); }, }); },
结论:图片没有填满整个 canvas,但是也是被压缩了
测试4:代码长宽=界面长宽,图片尺寸=界面长宽
onLoad: function (options) { var that = this; var url = "cloud://wxss-brick-0f77b1.7778-wxss-brick-0f77b1-1257336119/images/image1.jpeg"; wx.getImageInfo({ src: url, success: function (e2) { console.log('图像处理', 'getImageInfo', e2); that.drawImageToCanvas({ canvasId: '#previewCanvas', 300, height: 300, canvasWidth: 300, canvasHeight: 300, path: e2.path, success: function () {}, }); }, }); },
效果等同2.
测试结论:
canvas 代码设置的尺寸与图片的尺寸决定了图片在画布的表现;
界面尺寸仅仅是显示问题,和 canvas 数据无关。