深入理解Canvas中模糊问题产生的原因以及解决办法

我们在使用Canvas进行绘图时,经常会出现绘制的文字或者图片比较模糊,下面让我们看一下其产生的原因以及如何解决这个问题。

一、模糊产生的原因

1、style 和 canvas 中定义的宽高不一致造成的。

通常,在定义 canvas 时我们会这么写:

<canvas width="300" height="150" style="width: 300px; height: 150px;" id="canvas"></canvas>

其中,width、height 为 canvas 中绘制的大小,canvas 可以看成是一个画布,而 width、height 则分别代表这个画布所绘制区域的宽高。而 style 中定义的 width、height 则代表实际渲染到页面上的宽高。

那么问题来了,当 width、height 和 style 中定义的 width、height 不一致时,canvas 中绘制的元素会根据 width、height 进行缩放或者拉伸到 style 中所定义的 width、height,这就会导致所绘制的图像比较模糊。

2、所绘制的像素不足 1px。

在屏幕上绘制图像时,最少支持的也是绘制 1px,那么比如我们绘制 0.5px,canvas 会将使用填充算法将其扩展到 1px,如果所扩展的颜色跟原来的颜色一致,那么肯定没有问题,但是会产生锯齿状的一个效果,所以 canvas 会采取周围的颜色取一个平均值,这就会导致模糊的产生。所以尽量不要设置半个像素。

3、受到高清屏幕的影响。

在我们的普通屏幕上,设备像素比(Device Pixel Ratio:屏幕的物理像素 / css像素)为 1:1,在这种情况下不会产生模糊的问题。但是如果我们在一个 4k 的屏幕上,设备像素比为 1.5,那么也就是说屏幕的物理像素 / css像素等于 1.5,即一个 css 像素会渲染到 1.5 个设备像素上,这就会导致 css 像素会进行扩展,从而产生模糊的问题。

既然知道产生的原因,那么解决起来就很简单了。其主要的思想就是对 canvas 的 width、height 进行扩展,也就是扩展 canvas 画布的大小,但是 style 中的 width、height 并没有改变,这样 canvas 会进行缩放,这样一来,点就变多了,但是 canvas 本身的大小并没有改变(同二倍图、多倍图的原理相似)。

具体来说,有两种解决方法:

方法一:扩展 canvas 并对 canvas 的绘制上下文也进行扩展,相当于同时扩展画布和画笔。

const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const dpr = window.devicePixelRatio;

const { width, height } = canvas;

canvas.width = Math.round(width * dpr);
canvas.height = Math.round(height * dpr);

ctx.font = "bold 40px 宋体";
ctx.scale(dpr, dpr);

ctx.fillText("你好呀", canvas.clientWidth / 2, canvas.clientHeight / 2);

方法二:扩展 canvas,不扩展 canvas 绘制上下文,但在每次绘制元素时,需要对所绘制的元素进行扩展(即乘以一个设备像素比)。

const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const dpr = window.devicePixelRatio;

const { width, height } = canvas;

canvas.width = Math.round(width * dpr);
canvas.height = Math.round(height * dpr);

// ctx.scale(dpr, dpr);
ctx.font = "bold 40px 宋体";

ctx.fillText("你好呀", (canvas.clientWidth / 2) * dpr, (canvas.clientHeight / 2)  * dpr);

原文链接:https://juejin.cn/post/7353085048855937078 作者:送你颗糖呀

(0)
上一篇 2024年4月3日 上午10:47
下一篇 2024年4月3日 上午10:57

相关推荐

发表回复

登录后才能评论