画布图像线条模糊

45 html5 canvas

我有一个<div style="border:1px solid border;" />和帆布,使用以下方式绘制:

context.lineWidth = 1;
context.strokeStyle = "gray";
Run Code Online (Sandbox Code Playgroud)

绘图看起来相当模糊(lineWidth小于1创建更糟糕的图片),并且没有任何接近div的边界.是否可以使用画布获得与HTML相同的绘图质量?

var ctx = document.getElementById("canvas").getContext("2d");
ctx.lineWidth = 1;
ctx.moveTo(2, 2);
ctx.lineTo(98, 2);
ctx.lineTo(98, 98);
ctx.lineTo(2, 98);
ctx.lineTo(2, 2);
ctx.stroke();
Run Code Online (Sandbox Code Playgroud)
div {
  border: 1px solid black;
  width: 100px;
  height: 100px;
}
canvas, div {background-color: #F5F5F5;}
canvas {border: 1px solid white;display: block;}
Run Code Online (Sandbox Code Playgroud)
<table>
<tr><td>Line on canvas:</td><td>1px border:</td></tr>
<tr><td><canvas id="canvas" width="100" height="100"/></td><td><div>&nbsp;</div></td></tr>
</table>
Run Code Online (Sandbox Code Playgroud)

Ben*_*ius 67

我发现在CSS中设置画布大小会导致我的图像以模糊的方式显示.

试试这个:

<canvas id="preview" width="640" height="260"></canvas>
Run Code Online (Sandbox Code Playgroud)

根据我的帖子:HTML模糊画布图像

  • 多么奇怪的事.*这就是你继续滚动的原因.* (5认同)
  • 除此之外,您最好设置宽度和高度属性,尽管通过 CSS 设置这些属性。 (2认同)
  • 如果我被迫使用 CSS/Javascript 设置画布的高度/宽度,解决方法是什么?例如,在我的例子中,我需要画布具有响应能力,所以我需要动态计算它的尺寸并设置它。有任何想法吗?谢谢。 (2认同)

Mat*_*eer 49

在画布中绘制线条时,实际上需要跨越像素.在我看来,这是API中一个奇怪的选择,但易于使用:

而不是这个:

context.moveTo(10, 0);
context.lineTo(10, 30);
Run Code Online (Sandbox Code Playgroud)

做这个:

context.moveTo(10.5, 0);
context.lineTo(10.5, 30);
Run Code Online (Sandbox Code Playgroud)

深入了解HTML5的画布章节,很好地谈论这个问题
(寻找'ASK PROFESSOR MARKUP'框约1/4的方式)

  • 谢谢,这帮我解决了一个非常烦人的问题.我的做法略有不同我做了`context.translate(0.5,0.5);`在绘图之前然后``context.translate(-0.5,-0.5);`之后所以我没有必要添加0.5到一切 (6认同)
  • 这听起来很明显,但这是一个很容易犯的错误:确保您的浏览器视图缩放到 100% (Cmd-0)。我把我的放大了,花了十分钟才弄清楚为什么我的线条不会变得清晰。呃。 (2认同)

rev*_*gum 49

更简单的解决方法就是使用它:

context = canvas.context2d;    
context.translate(0.5, 0.5);
Run Code Online (Sandbox Code Playgroud)

从这里开始,你的坐标应该调整0.5像素.

  • 我的fillRect现在很模糊:( http://jsfiddle.net/Tysonzero/ydm21pkt/1/ (3认同)

Nic*_*aro 13

Mozilla 网站有关于如何更正画布分辨率的示例代码:https : //developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio

在此处输入图片说明

<!doctype html>
    <html lang="en">
    <head>
    <meta charset= "UTF-8">
    

    </head>
    
    <body>
        <div align = "center">
            <canvas id = "canvas">
    
            </canvas>
    
        </div>
          <script type="text/JavaScript">
            var canvas = document.getElementById('canvas');

            var ctx = canvas.getContext('2d');

            // Set display size (css pixels).
            var size = 200;
            canvas.style.width = size + "px";
            canvas.style.height = size + "px";

            // Set actual size in memory (scaled to account for extra pixel density).
            var scale = window.devicePixelRatio; // Change to 1 on retina screens to see blurry canvas.
            canvas.width = size * scale;
            canvas.height = size * scale;

            // Normalize coordinate system to use css pixels.
            ctx.scale(scale, scale);

            ctx.fillStyle = "#bada55";
            ctx.fillRect(10, 10, 300, 300);
            ctx.fillStyle = "#ffffff";
            ctx.font = '18px Arial';
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';

            var x = size / 2;
            var y = size / 2;

            var textString = "I love MDN";
            ctx.fillText(textString, x, y);
      </script>
    </body>
    </html>
Run Code Online (Sandbox Code Playgroud)

  • 我花了很长时间才找到这个伟大的解决方案。它值得更多的赞成票! (5认同)

小智 10

我使用的是视网膜显示屏和我发现,工作了我一个解决方案在这里.

小概述:

首先,您需要将画布的大小设置为您想要的两倍,例如:

canvas = document.getElementById('myCanvas');
canvas.width = 200;
canvas.height = 200;
Run Code Online (Sandbox Code Playgroud)

然后使用CSS将其设置为所需的大小:

canvas.style.width = "100px";
canvas.style.height = "100px";
Run Code Online (Sandbox Code Playgroud)

最后,您将绘图上下文缩放2:

canvas.getContext('2d').scale(2,2);
Run Code Online (Sandbox Code Playgroud)

  • 这基本上是正确的,但最好使用“ window.devicePixelRatio”:https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio (3认同)

小智 7

由于画布的虚拟尺寸 已缩放到其HTML元素实际尺寸,因此线条模糊。要解决此问题,您需要在绘制之前调整画布的虚拟尺寸:

function Draw () {
	var e, surface;
	e = document.getElementById ("surface");
	/* Begin size adjusting. */
	e.width = e.offsetWidth;
	e.height = e.offsetHeight;
	/* End size adjusting. */
	surface = e.getContext ("2d");
	surface.strokeRect (10, 10, 20, 20);
}
window.onload = Draw ()
Run Code Online (Sandbox Code Playgroud)
<!DOCTYPE html>
<html>
<head>
<title>Canvas size adjusting demo</title>
</head>
<body>
<canvas id="surface"></canvas>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

HTML:


Nor*_*ean 6

好吧,我已经一劳永逸地解决了这个问题。你需要做两件事:

  1. 将任何线条放置在 0.5 px 上。请参考这个,它提供了很好的解释:

https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Applying_styles_and_colors#A_lineWidth_example

  1. 画布本质上有两个高度和两个宽度。有画布的高度和宽度,还有元素的 css 样式高度和宽度。这些需要同步。

为此,您需要计算 css 高度和宽度:

 var myCanvasEl = document.getElementById('myCanvas');
 var ctx = myCanvasEl.getContext('2d');
 myCanvasEl.style.height = myCanvasEl.height / window.devicePixelRatio + "px";
 myCanvasEl.style.width = myCanvasEl.width / window.devicePixelRatio + "px";
 
Run Code Online (Sandbox Code Playgroud)

其中myCanvasEl.style.heightmyCanvasEl.style.width是元素的 CSS 样式高度和宽度,而myCanvasEl.heightmyCanvasEl.width是画布的高度和宽度。

旧答案(被上面取代):

这是我在 2020 年找到的最佳解决方案。请注意,我已将 devicePixelRatio 乘以 2:

 var size = 100;
 var scale = window.devicePixelRatio*2;
 context.width = size * scale;
 cartesian_001El.style.height = cartesian_001El.height / window.devicePixelRatio + "px";
 cartesian_001El.style.height = cartesian_001El.height / window.devicePixelRatio + "px";
 context.height = size * scale;
 context.scale(scale, scale);
Run Code Online (Sandbox Code Playgroud)