在画布上绘制1px粗线可创建2px粗线

Min*_*ure 45 html javascript line html5-canvas

在这个jsfiddle中,有一行lineWidth为1.

http://jsfiddle.net/mailrox/9bMPD/350/

例如:

ctx.lineWidth = 1;
Run Code Online (Sandbox Code Playgroud)

然而,当它在画布上绘制时,线是2px厚,如何创建1px粗线.

我可以绘制一个矩形(高度为1px),但我希望这条线也适用于对角线.那么你如何让这条线高1px?

谢谢!

Fer*_*bus 93

画布从一半像素计算

ctx.moveTo(50,150.5);
ctx.lineTo(150,150.5);
Run Code Online (Sandbox Code Playgroud)

所以从一半开始将解决它

修正版:http://jsfiddle.net/9bMPD/357/

这个答案解释了为什么它的工作原理.

  • 在 2018 年对我仍然有用。这是一个无需进行调整的简单修复:`context.translate(.5,.5);` 将所有内容偏移半个像素。做完需要做的事情,`context.setTransform(1, 0, 0, 1, 0, 0);`恢复偏移量。 (3认同)
  • 谢谢你的链接.我通过以下方式使用它:`ctx.moveTo(~~ x + .5,~~ y + .5);```~~`删除所有小数和`+ .5`,好吧,它增加了一半像素,所以线总是很好地对齐.有了这个,我还可以将`lineWidth`设置为1. (3认同)

Ric*_*ard 30

您还可以在X和Y方向上平移半个像素,然后使用整个值作为坐标(在某些情况下可能需要将它们舍入):

context.translate(0.5, 0.5)

context.moveTo(5,5);
context.lineTo(55,5);
Run Code Online (Sandbox Code Playgroud)

请记住,如果您调整画布大小,翻译将被重置 - 因此您将再次翻译.

这个答案解释了为什么它的工作原理.

  • 这是一个被低估的答案,感谢分享! (2认同)

ton*_*and 8

或者,正如这个答案所述,要获得宽度为1,您需要从半像素开始.

ctx.moveTo(50.5,150.5);
ctx.lineTo(150.5,150.5);
Run Code Online (Sandbox Code Playgroud)

http://jsfiddle.net/9bMPD/355/


Iev*_*ida 6

对我来说,只有不同的“像素完美”技术的组合有助于存档结果:

  1. 使用像素比率获取和缩放画布:

    pixelRatio = window.devicePixelRatio/ctx.backingStorePixelRatio

  2. 在调整大小时缩放画布(避免画布默认拉伸缩放)。

  3. 将 lineWidth 与 pixelRatio 相乘以找到合适的“真实”像素线粗:

    context.lineWidth = 厚度 * pixelRatio;

  4. 检查线的粗细是奇数还是偶数。将像素比率的一半添加到奇数厚度值的线位置。

    x = x + pixelRatio/2;

奇数线将放置在像素的中间。上面的线用于稍微移动它。

function getPixelRatio(context) {
  dpr = window.devicePixelRatio || 1,
    bsr = context.webkitBackingStorePixelRatio ||
    context.mozBackingStorePixelRatio ||
    context.msBackingStorePixelRatio ||
    context.oBackingStorePixelRatio ||
    context.backingStorePixelRatio || 1;

  return dpr / bsr;
}


var canvas = document.getElementById('canvas');
var context = canvas.getContext("2d");
var pixelRatio = getPixelRatio(context);
var initialWidth = canvas.clientWidth * pixelRatio;
var initialHeight = canvas.clientHeight * pixelRatio;


window.addEventListener('resize', function(args) {
  rescale();
  redraw();
}, false);

function rescale() {
  var width = initialWidth * pixelRatio;
  var height = initialHeight * pixelRatio;
  if (width != context.canvas.width)
    context.canvas.width = width;
  if (height != context.canvas.height)
    context.canvas.height = height;

  context.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
}

function pixelPerfectLine(x) {

  context.save();
  context.beginPath();
  thickness = 1;
  // Multiple your stroke thickness  by a pixel ratio!
  context.lineWidth = thickness * pixelRatio;

  context.strokeStyle = "Black";
  context.moveTo(getSharpPixel(thickness, x), getSharpPixel(thickness, 0));
  context.lineTo(getSharpPixel(thickness, x), getSharpPixel(thickness, 200));
  context.stroke();
  context.restore();
}

function pixelPerfectRectangle(x, y, w, h, thickness, useDash) {
  context.save();
  // Pixel perfect rectange:
  context.beginPath();

  // Multiple your stroke thickness by a pixel ratio!
  context.lineWidth = thickness * pixelRatio;
  context.strokeStyle = "Red";
  if (useDash) {
    context.setLineDash([4]);
  }
  // use sharp x,y and integer w,h!
  context.strokeRect(
    getSharpPixel(thickness, x),
    getSharpPixel(thickness, y),
    Math.floor(w),
    Math.floor(h));
  context.restore();
}

function redraw() {
  context.clearRect(0, 0, canvas.width, canvas.height);
  pixelPerfectLine(50);
  pixelPerfectLine(120);
  pixelPerfectLine(122);
  pixelPerfectLine(130);
  pixelPerfectLine(132);
  pixelPerfectRectangle();
  pixelPerfectRectangle(10, 11, 200.3, 443.2, 1, false);
  pixelPerfectRectangle(41, 42, 150.3, 443.2, 1, true);
  pixelPerfectRectangle(102, 100, 150.3, 243.2, 2, true);
}

function getSharpPixel(thickness, pos) {

  if (thickness % 2 == 0) {
    return pos;
  }
  return pos + pixelRatio / 2;

}

rescale();
redraw();
Run Code Online (Sandbox Code Playgroud)
canvas {
  image-rendering: -moz-crisp-edges;
  image-rendering: -webkit-crisp-edges;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  width: 100vh;
  height: 100vh;
}
Run Code Online (Sandbox Code Playgroud)
<canvas id="canvas"></canvas>
Run Code Online (Sandbox Code Playgroud)

Resize 事件不会在截图中触发,因此您可以尝试github上的文件