canvas 生成图片模糊

参考文件:
https://blog.csdn.net/qq_41887214/article/details/123173072
https://juejin.cn/post/6844903828916011022
https://www.jb51.net/html5/815034.html

在解决这个问题之前,必须了解以下背景知识
1.关于屏幕的一些基础知识:

  • 物理像素(DP)

物理像素也称设备像素,我们常听到的手机的分辨率及为物理像素,比如 iPhone 7的物理分辨率为750 * 1334。屏幕是由像素点组成的,也就是说屏幕的水平方向有750的像素点,垂直方向上有1334个像素点

  • 设备独立像素(DIP)

也称为逻辑像素,比如Iphone4和Iphone3GS的尺寸都是3.5寸,iphone4的物理分辨率是640 * 980,而3gs只有320 * 480,假如我们按照真实布局取绘制一个320px宽度的图像时,在iphone4上只有一半有内容,剩下的一半则是一片空白,为了避免这种问题,我们引入了逻辑像素,将两种手机的逻辑像素都设置为320px,方便绘制

  • 设备像素比(DPR)

上面的设备独立像素说到底是为了方便计算,我们统一了设备的逻辑像素,但是每个逻辑像素所代表的物理像素却不是确定的,为了确定在未缩放情况下,物理像素和逻辑像素的关系,我们引入了设备像素比(DPR)这个概念。
设备像素比 = 设备像素 / 逻辑像素
请添加图片描述

从上面的图可以看出,在同样大小的逻辑像素下,高清屏所具有的物理像素更多。普通屏幕下,1个逻辑像素对应1个物理像素,而在dpr = 2的高清屏幕下,1个逻辑像素由4个物理像素组成。这也是为什么高清屏更加细腻的原因。

2.关于canvas的一些基础知识

  • canvas绘制的是位图
  • canvas的width和height属性
canvas的width和height属性与style的width,height 不同。应注意区分:
<canvas width="600" height="300" style="width: 300px; height: 150px"></canvas>
style中的width和height分别代表canvas这个元素在界面上所占据的宽高,即样式上的宽高
attribute中的width和height则代表canvas实际像素的宽高
也就是就是1个逻辑像素实际上由2个canvas像素填充。
例如: 示例一: canvas width="300" height="150" style="width: 300px; height: 150px" // 红色
示例二:canvas width="600" height="300" style="width: 300px; height: 150px" // 蓝色
也就项上述的图片展示一致  红色为普通屏  蓝色为高清屏;

图片模糊原因:
canvas 绘制的图形是位图,即栅格图像或点阵图像,当将它渲染到高清屏时,会被放大,每个像素点会用 devicePixelRatio 的平方个物理像素点来渲染,因此图片会变得模糊。

解决方法:
放大 devicePixelRatio 倍 canvas 的宽高,然后再用css缩小回到你想要的理想像素

uniapp 解决问题实例:
1、 canvas 节点
<!-- 避免图片失真,获取设备像素比设置画布大小,css样式在设置内容块宽高 -->
<canvas canvas-id="mycanvas" :style="'width: '+popWidth*devicePixelRatio+'px;height: '+canvasHeight*devicePixelRatio+'px;transform:scale('+1/devicePixelRatio+'); transform-origin: 0px 0px;position: fixed;opacity: 0;top: -'+canvasHeight+100+'px;'"></canvas>

2、获取设备像素比
uni.getSystemInfo({
    
    
    success(res) {
    
    
    	that.popWidth = res.windowWidth;
    	// 设备像素比大于1
    	if (res.devicePixelRatio > 1) {
    
    
    		that.devicePixelRatio = res.devicePixelRatio;
    	}
    }
});
3、绘制
let ctx = uni.createCanvasContext('mycanvas', this);  // 创建canvas对象
ctx.setFillStyle('#fff');
// 避免二维码失真,导致识别二维码失败;
// 获取设置像素比。绘制设备像素比相符的画布内容,在csstranform设置节点样式缩放,transform-origin基准设置为0,0;
// 这样获取到的画布图片内容就不会失真了。
ctx.fillRect(0, 0, that.popWidth*that.devicePixelRatio, that.canvasHeight*that.devicePixelRatio); // that.canvasHeight 为你设计图的画布高度;
.....

猜你喜欢

转载自blog.csdn.net/qq_43148113/article/details/124816270