Canvas drawings, like lines, are blurry

前端 未结 10 890
野的像风
野的像风 2020-11-27 15:15

I have a

and canvas, which is drawn using:

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


        
相关标签:
10条回答
  • 2020-11-27 15:51

    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 :

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

    And finally you scale the drawing context by 2 :

    canvas.getContext('2d').scale(2,2);
    
    0 讨论(0)
  • 2020-11-27 15:52

    Ok, I've figured this out once and for all. You need to do two things:

    1. place any lines on 0.5 px. Refer to this, which provides a great explanation:

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

    1. There are essentially two heights and two widths associated with the canvas. There is the canvas height and width and then there is the css style height and width of the element. These need to be in sync.

    To do this, you need to calculate the css height and width as:

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

    where myCanvasEl.style.height and myCanvasEl.style.widthis the css styling height and width of the element, while myCanvasEl.height and myCanvasEl.width is the height and width of the canvas.

    OLD ANSWER (superseded by above):

    This is the best solution I've found in 2020. Notice I've multiplied the devicePixelRatio by 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);
    
    0 讨论(0)
  • 2020-11-27 15:54

    To avoid this issue in animation I 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.

    HTML:

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

    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:

      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
        }
      }
    
    0 讨论(0)
  • 2020-11-27 15:55

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

    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:

    0 讨论(0)
提交回复
热议问题