这篇文章主要区分 canvas 以下两种尺寸的区别与联系:
canvas.width
、canvas.height
:device pixel(物理像素)canvas.style.width
、canvas.style.height
:css pixel(逻辑像素)微信小程序 canvas 2d 官方例子是这样的:
<!-- index.wxml -->
<canvas type="2d" id="myCanvas"></canvas>
//index.js
Page({
onReady() {
const query = wx.createSelectorQuery();
query
.select("#myCanvas")
.fields({ node: true, size: true })
.exec((res) => {
const canvas = res[0].node;
const ctx = canvas.getContext("2d");
// 根据 dpr 做相关设置
const dpr = wx.getSystemInfoSync().devicePixelRatio;
canvas.width = res[0].width * dpr;
canvas.height = res[0].height * dpr;
ctx.scale(dpr, dpr);
ctx.fillRect(0, 0, 100, 100);
});
},
});
如果 canvas 组件没有设置 style,那默认 style 的就是 width: 300px; height 150px
,在 wxml 中的尺寸都是 css pixel,设备会把 css pixel(逻辑像素) 乘以 devicePixelRatio 转换成 device pixel(物理像素) 再显示在屏幕上。iPhone 6 的屏幕分辨率是 375 x 667,这个数字是 css pixel,它的 device pixel 其实是 750 x 1334,大多数产品的参数所标注的屏幕分辨率都是 device pixel。
记住,在 wxml 显示的是 css pixel,但是在 js 写的 canvas 代码是 device pixel 尺寸,所以你会看到上面的例子通过 res[0].width
拿到这个 canvas 组件的 css pixel,然后乘以 dpr 转换成这个 canvas 的 device pixel。如果不转换,那整个图片都会被缩小。
canvas.width
和 canvas.style.width
是不同的东西,前者定义了 canvas 的座标体系,而后者定义 canvas 实际显示的尺寸,显示尺寸可以不等于实际尺寸,此时图片可能整体放大或缩小了,甚至被压缩或拉伸了。但通常的做法是 canvas.width = canvas.style.width * dpr
,这样可以避免 canvas 上的内容变得模糊。
ctx.scale(dpr,dpr)
的作用是,用微信小程序文档的一句话来说,就是:
在调用后,之后创建的路径其横纵坐标会被缩放。多次调用倍数会相乘。
所以下面这个代码:
ctx.scale(dpr, dpr);
ctx.fillRect(0, 0, 100, 100);
相当于下面这个代码:
ctx.fillRect(0 * dpr, 0 * dpr, 100 * dpr, 100 * dpr);
有时候之所以写 ctx.scale(dpr, dpr)
,是因为接下来可以用 css pixel 去画这个 canvas,毕竟 css pixel 是设计师采用的尺寸,不用每次都乘以 dpr。
drawImage(imageResource, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
中,sWidth 和 sHeight 都是图片的 css pixel 尺寸,如果不确定可以用 wx.getImageInfo()
获取,后面四个参数都是 canvas 的座标位置,根据 canvas.width
和 canvas.height
以及 ctx.scale(dpr, dpr)
确定。
wx.canvasToTempFilePath
可以设置这些选项:
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: 50,
height: 50,
destWidth: 100,
destHeight: 100,
canvas: "myCanvas",
success(res) {
console.log(res.tempFilePath);
},
});
前面四个参数是 canvas 的 css 座标,destWidth 和 destHeight 是最终输出的图片的 css 尺寸,即 destWidth: 100
其实相当于在输出的图片添加 image.style.width = 100px
。destWidth 和 destHeight 要不小于 width 和 height,否则会变模糊。