Подтвердить что ты не робот

Холст HTML5 и сглаживание

Как включить сглаживание на холсте.

Следующий код не рисует гладкую линию:

var context = mainCanv.getContext("2d");
if (context) {
   context.moveTo(0,0);
   context.lineTo(100,75);

   context.strokeStyle = "#df4b26";
   context.lineWidth = 3;
   context.stroke();
}
4b9b3361

Ответ 2

Вы можете переводить холст на половину пикселя.

ctx.translate(0.5, 0.5);

Первоначально точка позиционирования холста между физическими пикселями.

Ответ 3

Мне не нужно включать анти-псевдоним, потому что он по умолчанию, но мне нужно отключить его. И если его можно отключить, он также может быть включен.

ctx.imageSmoothingEnabled = true;

Я обычно закрываю его, когда я работаю над своим холстом rpg, поэтому, когда я увеличиваю изображение, не выгляжу размытым.

Ответ 4

Здесь обходной путь, который требует рисования линий по пикселям, но предотвратит сглаживание.

// some helper functions
// finds the distance between points
function DBP(x1,y1,x2,y2) {
    return Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
}
// finds the angle of (x,y) on a plane from the origin
function getAngle(x,y) { return Math.atan(y/(x==0?0.01:x))+(x<0?Math.PI:0); }
// the function
function drawLineNoAliasing(ctx, sx, sy, tx, ty) {
    var dist = DBP(sx,sy,tx,ty); // length of line
    var ang = getAngle(tx-sx,ty-sy); // angle of line
    for(var i=0;i<dist;i++) {
        // for each point along the line
        ctx.fillRect(Math.round(sx + Math.cos(ang)*i), // round for perfect pixels
                     Math.round(sy + Math.sin(ang)*i), // thus no aliasing
                     1,1); // fill in one pixel, 1x1
    }
}

В основном вы найдете длину строки и шаг за шагом перемещаете эту строку, округляя каждую позицию и заполняя пиксель.

Назовите его

var context = cv.getContext("2d");
drawLineNoAliasing(context, 20,30,20,50); // line from (20,30) to (20,50)

Ответ 5

Это сейчас 2018 год, и у нас наконец есть дешевые способы сделать что-то вокруг него...

Действительно, поскольку API-интерфейс 2d теперь имеет свойство filter, и что это свойство фильтра может принимать SVGFilters, мы можем построить SVGFilter, который будет сохранять только полностью непрозрачные пиксели из наших чертежей и, таким образом, устранить антиалиасинг по умолчанию.

Таким образом, он не будет деактивировать сглаживание как таковое, но обеспечивает дешевый способ как с точки зрения реализации, так и для выполнения действий по удалению всех полупрозрачных пикселей при рисовании.

Я не специалист SVGFilters, поэтому может быть лучший способ сделать это, но для примера я буду использовать узел <feComponentTransfer> чтобы захватить только полностью непрозрачные пиксели.

var ctx = canvas.getContext('2d');
ctx.fillStyle = '#ABEDBE';
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.fillStyle = 'black';
ctx.font = '14px sans-serif';
ctx.textAlign = 'center';

// first without filter
ctx.fillText('no filter', 60, 20);
drawArc();
drawTriangle();
// then with filter
ctx.setTransform(1, 0, 0, 1, 120, 0);
ctx.filter = 'url(#remove-alpha)';
// and do the same ops
ctx.fillText('no alpha', 60, 20);
drawArc();
drawTriangle();

// to remove the filter
ctx.filter = 'none';


function drawArc() {
  ctx.beginPath();
  ctx.arc(60, 80, 50, 0, Math.PI * 2);
  ctx.stroke();
}

function drawTriangle() {
  ctx.beginPath();
  ctx.moveTo(60, 150);
  ctx.lineTo(110, 230);
  ctx.lineTo(10, 230);
  ctx.closePath();
  ctx.stroke();
}
// unrelated
// simply to show a zoomed-in version
var zCtx = zoomed.getContext('2d');
zCtx.imageSmoothingEnabled = false;
canvas.onmousemove = function drawToZoommed(e) {
  var x = e.pageX - this.offsetLeft,
    y = e.pageY - this.offsetTop,
    w = this.width,
    h = this.height;
    
  zCtx.clearRect(0,0,w,h);
  zCtx.drawImage(this, x-w/6,y-h/6,w, h, 0,0,w*3, h*3);
}
<svg width="0" height="0" style="position:absolute;z-index:-1;">
  <defs>
    <filter id="remove-alpha" x="0" y="0" width="100%" height="100%">
      <feComponentTransfer>
        <feFuncA type="discrete" tableValues="0 1"></feFuncA>
      </feComponentTransfer>
      </filter>
  </defs>
</svg>

<canvas id="canvas" width="250" height="250" ></canvas>
<canvas id="zoomed" width="250" height="250" ></canvas>

Ответ 6

Если вам нужен контроль уровня над уровнем содержимого на холсте, вы можете использовать createImageData и putImageData.

HTML:

<canvas id="qrCode" width="200", height="200">
  QR Code
</canvas>

И JavaScript:

function setPixel(imageData, pixelData) {
  var index = (pixelData.x + pixelData.y * imageData.width) * 4;
    imageData.data[index+0] = pixelData.r;
    imageData.data[index+1] = pixelData.g;
    imageData.data[index+2] = pixelData.b;
    imageData.data[index+3] = pixelData.a;
}

element = document.getElementById("qrCode");
c = element.getContext("2d");

pixcelSize = 4;
width = element.width;
height = element.height;


imageData = c.createImageData(width, height);

for (i = 0; i < 1000; i++) {
  x = Math.random() * width / pixcelSize | 0; // |0 to Int32
  y = Math.random() * height / pixcelSize| 0;

  for(j=0;j < pixcelSize; j++){
    for(k=0;k < pixcelSize; k++){
     setPixel( imageData, {
         x: x * pixcelSize + j,  
         y: y * pixcelSize + k,
         r: 0 | 0,
         g: 0 | 0,
         b: 0 * 256 | 0,
         a: 255 // 255 opaque
       });
      }
  }
}

c.putImageData(imageData, 0, 0);

Рабочий пример здесь