概述
微信小程序的 Canvas 實在太難用,這裏記錄一些場景經驗,提高認識。
畫圖的尺寸問題
在頁面聲明一個 canvas
<canvas id="previewCanvas" c type="2d" style="width: {{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', width: 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', width: 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', width: 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', width: 300, height: 300, canvasWidth: 300, canvasHeight: 300, path: e2.path, success: function () {}, }); }, }); },
效果等同2.
測試結論:
canvas 代碼設置的尺寸與圖片的尺寸決定了圖片在畫布的表現;
界面尺寸僅僅是顯示問題,和 canvas 數據無關。