Html 画布绘图,如线条,是模糊的

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8696631/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 12:16:05  来源:igfitidea点击:

Canvas drawings, like lines, are blurry

htmlcanvas

提问by revgum

I have a <div style="border:1px solid border;" />and canvas, which is drawn using:

我有一个<div style="border:1px solid border;" />画布,它是使用以下方法绘制的:

context.lineWidth = 1;
context.strokeStyle = "gray";

The drawing looks quite blurry (lineWidth less than one creates even worse picture), and nothing near to the div's border. Is it possible to get the same quality of drawing as HTML using canvas?

绘图看起来很模糊(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();
div {
  border: 1px solid black;
  width: 100px;
  height: 100px;
}
canvas, div {background-color: #F5F5F5;}
canvas {border: 1px solid white;display: block;}
<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>

回答by Ben Pretorius

I found that setting the canvas size in CSS caused my images to be displayed in a blurry manner.

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

Try this:

尝试这个:

<canvas id="preview" width="640" height="260"></canvas>

as per my post: HTML Blurry Canvas Images

根据我的帖子:HTML Blurry Canvas Images

回答by Matt Greer

When drawing lines in canvas, you actually need to straddle the pixels. It was a bizarre choice in the API in my opinion, but easy to work with:

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

instead of this:

而不是这个:

context.moveTo(10, 0);
context.lineTo(10, 30);

do this:

做这个:

context.moveTo(10.5, 0);
context.lineTo(10.5, 30);

dive into HTML5's canvas chapter talks about this nicely
(look for the 'ASK PROFESSOR MARKUP' box about 1/4th of the way down)

潜入 HTML5 的画布章节很好地讨论了这一点
(寻找大约 1/4 处的“ASK PROFESSOR MARKUP”框)

回答by revgum

Even easier fix is to just use this:

更简单的解决方法是使用这个:

context = canvas.context2d;    
context.translate(0.5, 0.5);

From here on out your coordinates should be adjusted by that 0.5 pixel.

从这里开始,您的坐标应调整为 0.5 像素。

回答by LittleJoe

I use a retina display and I found a solution that worked for me here.

我使用视网膜显示器,我在这里找到了一个对我有用的解决方案。

Small recap :

小回顾:

First you need to set the size of your canvas twice as large as you want it, for example :

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

canvas = document.getElementById('myCanvas');
canvas.width = 200;
canvas.height = 200;

Then using CSS you set it to the desired size :

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

canvas.style.width = "100px";
canvas.style.height = "100px";

And finally you scale the drawing context by 2 :

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

canvas.getContext('2d').scale(2,2);

回答by R0bur

Lines are blurred because the canvas virtual sizeis zoomed toits HTML element actual size. To overcome this issue you need to adjust canvas virtual size before drawing:

线条模糊是因为画布虚拟大小被缩放到其 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 ()
<!DOCTYPE html>
<html>
<head>
<title>Canvas size adjusting demo</title>
</head>
<body>
<canvas id="surface"></canvas>
</body>
</html>

HTML:

HTML:

回答by Nic Scozzaro

As @langpavel mentioned in a comment, the Mozilla website has example code for how to correct resolution in a canvas: https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio

正如@langpavel 在评论中提到的,Mozilla 网站上有关于如何更正画布分辨率的示例代码:https: //developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio

enter image description here

在此处输入图片说明

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);

回答by Normajean

This is the best solution I've found in 2020. Notice I've multiplied the devicePixelRatio by 2:

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

 var size = 100;
 var scale = window.devicePixelRatio*2;
 context.width = size * scale;
 context.height = size * scale;
 context.scale(scale, scale);

回答by Imran Bughio

To avoid this issue in animationI would like to share a small demo.

为了避免动画中的这个问题,我想分享一个小演示

Basically I am checking increment values each time & jumping in a set of 1px by removing float values.

基本上,我每次都检查增量值并通过删除浮点值来跳入一组 1px。

HTML:

HTML:

<canvas id="canvas" width="600" height="600"></canvas>

CSS:

CSS:

  html, body{
    height: 100%;
  }
  body{
    font-family: monaco, Consolas,"Lucida Console", monospace;
    background: #000;
  }

  canvas{
    position: fixed;
    top: 0;
    left: 0;
    transform: translateZ(0);
  }

JS:

JS:

  canvas = document.getElementById('canvas');
  ctx = canvas.getContext('2d');

  ctx.translate(0.5, 0.5);

  var i = 0;
  var iInc = 0.005;
  var range = 0.5;

  raf = window.requestAnimationFrame(draw);

  function draw() {
    var animInc = EasingFunctions.easeInQuad(i) * 250;
    ctx.clearRect(0, 0, 600, 600);
    ctx.save();
    ctx.beginPath();
    ctx.strokeStyle = '#fff';
    var rectInc = 10 + animInc;

    // Avoid Half Pixel
    rectIncFloat = rectInc % 1; // Getting decimal value.
    rectInc = rectInc - rectIncFloat; // Removing decimal.

    // console.log(rectInc);
    ctx.rect(rectInc, rectInc, 130, 60);
    ctx.stroke();
    ctx.closePath();

    ctx.font = "14px arial";
    ctx.fillStyle = '#fff';
    ctx.textAlign = 'center';
    ctx.fillText("MAIN BUTTON", 65.5 + rectInc, 35.5 + rectInc);

    i += iInc;

    if (i >= 1) {
      iInc = -iInc;
    }
    if (i <= 0) {
      iInc = Math.abs(iInc);
    }

    raf = window.requestAnimationFrame(draw);
  }


  // Easing
  EasingFunctions = {
    // no easing, no acceleration
    linear: function(t) {
      return t
    },
    // accelerating from zero velocity
    easeInQuad: function(t) {
      return t * t
    },
    // decelerating to zero velocity
    easeOutQuad: function(t) {
      return t * (2 - t)
    },
    // acceleration until halfway, then deceleration
    easeInOutQuad: function(t) {
      return t < .5 ? 2 * t * t : -1 + (4 - 2 * t) * t
    },
    // accelerating from zero velocity 
    easeInCubic: function(t) {
      return t * t * t
    },
    // decelerating to zero velocity 
    easeOutCubic: function(t) {
      return (--t) * t * t + 1
    },
    // acceleration until halfway, then deceleration 
    easeInOutCubic: function(t) {
      return t < .5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1
    },
    // accelerating from zero velocity 
    easeInQuart: function(t) {
      return t * t * t * t
    },
    // decelerating to zero velocity 
    easeOutQuart: function(t) {
      return 1 - (--t) * t * t * t
    },
    // acceleration until halfway, then deceleration
    easeInOutQuart: function(t) {
      return t < .5 ? 8 * t * t * t * t : 1 - 8 * (--t) * t * t * t
    },
    // accelerating from zero velocity
    easeInQuint: function(t) {
      return t * t * t * t * t
    },
    // decelerating to zero velocity
    easeOutQuint: function(t) {
      return 1 + (--t) * t * t * t * t
    },
    // acceleration until halfway, then deceleration 
    easeInOutQuint: function(t) {
      return t < .5 ? 16 * t * t * t * t * t : 1 + 16 * (--t) * t * t * t * t
    }
  }

回答by Dennis Anonymus Minecrafter

in order to get rid of the blurryness you need to set the size of the canvas in two manners: first withcanvas.width = yourwidthhere;and canvas.height = yourheighthere;second by setting the css attribute either by js or a stylesheet

为了摆脱模糊,您需要以两种方式设置画布的大小:第一种方式canvas.width = yourwidthhere;canvas.height = yourheighthere;第二种方式是通过 js 或样式表设置 css 属性

回答by Adam O Ceallaigh

HTML:

HTML:

<canvas class="canvas_hangman"></canvas> 

JS:

JS:

function setUpCanvas(){
      canvas = document.getElementsByClassName("canvas_hangman")[0];
      ctx = canvas.getContext('2d');
      ctx.translate(0.5, 0.5);

      // Set display size (vw/vh).
      var sizeWidth = 80 * window.innerWidth / 100,
          sizeHeight = 100 * window.innerHeight / 100 || 766; 

      // console.log(sizeWidth, sizeHeight);
      //Setting the canvas site and width to be responsive 
      canvas.width = sizeWidth;
      canvas.height = sizeHeight;
      canvas.style.width = sizeWidth;
      canvas.style.height = sizeHeight;
 }
 window.onload = setUpCanvas();

This perfectly sets up your HTML canvas to draw on, in a responsive manner too:)

这也可以以响应方式完美地设置您的 HTML 画布以进行绘制:)