Ответ 1
Сглаживание не может быть включено или выключено и управляется браузером.
Как включить сглаживание на холсте.
Следующий код не рисует гладкую линию:
var context = mainCanv.getContext("2d");
if (context) {
context.moveTo(0,0);
context.lineTo(100,75);
context.strokeStyle = "#df4b26";
context.lineWidth = 3;
context.stroke();
}
Сглаживание не может быть включено или выключено и управляется браузером.
Вы можете переводить холст на половину пикселя.
ctx.translate(0.5, 0.5);
Первоначально точка позиционирования холста между физическими пикселями.
Мне не нужно включать анти-псевдоним, потому что он по умолчанию, но мне нужно отключить его. И если его можно отключить, он также может быть включен.
ctx.imageSmoothingEnabled = true;
Я обычно закрываю его, когда я работаю над своим холстом rpg, поэтому, когда я увеличиваю изображение, не выгляжу размытым.
Здесь обходной путь, который требует рисования линий по пикселям, но предотвратит сглаживание.
// 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)
Это сейчас 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>
Если вам нужен контроль уровня над уровнем содержимого на холсте, вы можете использовать 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);