73 votes

Les dessins sur toile, comme les lignes, sont flous

J'ai un <div style="border:1px solid border;" /> et le canevas, qui est dessiné en utilisant :

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

Le dessin est assez flou (une largeur de ligne inférieure à un crée une image encore pire), et rien n'est proche de la bordure de la division. Est-il possible d'obtenir la même qualité de dessin que le HTML en utilisant canvas ?

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>

15voto

R0bur Points 305

Les lignes sont floues parce que la toile taille virtuelle est zoomé sur son élément HTML taille réelle . Pour surmonter ce problème, vous devez ajuster la taille virtuelle du canevas avant de dessiner :

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 :

5voto

Normajean Points 551

Ok, j'ai compris une fois pour toutes. Tu dois faire deux choses :

  1. placer toute ligne sur 0,5 px. Référez-vous à ceci, qui fournit une excellente explication :

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

  1. Il y a essentiellement deux hauteurs et deux largeurs associées à la toile. Il y a la hauteur et la largeur du canevas, puis la hauteur et la largeur du style css de l'élément. Ces deux éléments doivent être synchronisés.

Pour ce faire, vous devez calculer la hauteur et la largeur css comme :

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

myCanvasEl.style.height et myCanvasEl.style.width est la hauteur et la largeur de l'élément selon le style css, tandis que myCanvasEl.height et myCanvasEl.width est la hauteur et la largeur de la toile.

ANCIENNE RÉPONSE (remplacée par la réponse ci-dessus) :

C'est la meilleure solution que j'ai trouvée en 2020. Remarquez que j'ai multiplié le devicePixelRatio par 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);

1voto

Imran Bughio Points 3080

Pour éviter ce problème dans animation Je voudrais partager une petite Démonstration .

En fait, je vérifie les valeurs d'incrémentation à chaque fois et je saute dans un ensemble de 1px en supprimant les valeurs flottantes.

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
    }
  }

1voto

Fab Sa Points 1155

Une autre chose dont personne n'a parlé ici lorsque les images sont mises à l'échelle (ce qui était mon problème) est imageSmoothingEnabled .

Le site imageSmoothingEnabled propriété de l'interface CanvasRenderingContext2D, qui fait partie de l'API Canvas, détermine si les images mises à l'échelle sont lissées (true, default) ou non (false) . Lorsque vous obtenez la propriété imageSmoothingEnabled, la dernière valeur à laquelle elle a été définie est renvoyée.

Cette propriété est utile pour les jeux et autres applications qui utilisent le pixel art. Lors de l'agrandissement des images, l'algorithme de redimensionnement par défaut rend les pixels flous. Définissez cette propriété sur false pour conserver la netteté des pixels.

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/imageSmoothingEnabled

Pour le désactiver, il suffit de mettre la propriété à false :

ctx.imageSmoothingEnabled = false;

0voto

Java Wizard Points 39

Pour éliminer le flou, vous devez définir la taille de la toile de deux manières : d'abord avec canvas.width = yourwidthhere; et canvas.height = yourheighthere; ensuite en définissant l'attribut css soit par js soit par une feuille de style

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X