微信小程序 MiniProgram
Canvas DrawImage变形问题
先来看段代码:
wx.createSelectorQuery().in(this).select('#output')
.fields({
node: true,
size: true
})
.exec((res2) => {
var canvas = res2[0].node;
const output = canvas.getContext('2d')
let img = canvas.createImage(); //创建img对象
img.onload = () => {
output.clearRect(0, 0, canvas._width, canvas._height)
output.drawImage(img, 0, 0, canvas._width, canvas._height); //drawImage(要绘画的元素, x轴, y轴)
};
img.src = remoteSrc;
});
其中这个图片的宽高跟canvas的宽高是完全一致的,但是通过上面的输出后,图片呈现出被裁剪以及变形的情况
DrawImage的文档地址
DrawImage的参数主要包含两部分,一是从图中的截取哪一部分,二是将截取的部分粘贴到canvas的哪个位置
其中第一部分可以不要,表达截取整个图片,形如上面代码中写的
找遍全网都没有找到解决办法,后来在canvas的示例中看到一段代码
// canvas.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')
const dpr = wx.getSystemInfoSync().pixelRatio
canvas.width = res[0].width * dpr
canvas.height = res[0].height * dpr
ctx.scale(dpr, dpr)
ctx.fillRect(0, 0, 100, 100)
})
}
})
依样画葫芦试了下,图片不再变形,大小也正确
我理解的如下:
scale 缩放,缩放画布,缩放完画布后,新画到画布的图,也会随着缩放。
设备像素比Dpr=物理像素/css像素 ,假如dpr为2,那么手机一般是2个像素当1个像素进行显示,假如图片尺寸是200px,实际上你看到的是100px
微信小程序默认canvas的width,height分别为300,150
回到最初,显示会变大变形的问题,
- 虽然canvas通过css控制为 300,300,但是这个只是css的,实际的canvas宽高还是300,150
- 现在将300px*300px的图片画到canvas中,由于使用了canvas的_height,也就是css的高度300,但实际上canvas只有150的高,那么将图将被切掉一半高度
- canvas只有一半的图片,再通过canvas的css进行展示,有就是将300*150的图片展示为300*300,最终呈现的效果如下
既然知道了变形的原因,也就是canvas实际宽高的问题,那么就知道如何解决
- 将canvas的实际宽高进行重置,这样300*300的图片画到了300*300的canvas上,图片不再被裁剪
- const dpr = wx.getSystemInfoSync().pixelRatio canvas.width = res[0].width * dpr canvas.height = res[0].height * dpr
- 上面的代码有一个细节,canvas宽高都乘上了dpr值,假如dpr值是2,那么300的图,扩大为600的图,画在600的canvas上,为什么要这样做?这里有一个二倍图的概念,假如css使用的是rpx,那么这个图会根据屏幕自动缩小,为了能够匹配这种缩小,就需要将原图扩大,也就是乘上dpr