【问题标题】:In Html5, draw from (0.5, 0) to (0.5, 600) to get a 1-pixel thick line on canvas. The 0.5 is strange?在 Html5 中,从 (0.5, 0) 到 (0.5, 600) 绘制以在画布上得到 1 像素粗线。 0.5很奇怪?
【发布时间】:2010-09-07 10:09:45
【问题描述】:

我正在阅读一本关于 Html5 和画布的书,以下代码将生成 1 像素粗线...它使用 0.5 作为坐标。如果将其更改为 0 或 10,或某个整数,则线条将是灰色的,并且 2 像素粗。这是为什么?这是我最近看到的最奇怪的事情......之前在 Apple 或 Win32 API 上的所有编程,它们都是通过整数坐标进行的。

<!DOCTYPE html>

<body>
<canvas id="c" width="800" height="600"></canvas>
</body>

<script>

var c_canvas = document.getElementById("c")
var context = c_canvas.getContext("2d")

for (x = 0.5; x < 500; x += 10) {
  context.moveTo(x, 0)
  context.lineTo(x, 375)
}
context.strokeStyle = "#000"
context.stroke()


</script>

另一个奇怪的事情是,要获得一个 1 像素乘 1 像素的黑点,我必须为 x 绘制 0.5,但为 y 使用整数

for (x = 0.5; x < 500; x += 10) {
  context.moveTo(x, 0)
  context.lineTo(x, 1)
}

如果我使用以下内容,那么我会得到一个灰色的“更长的点”

for (x = 0.5; x < 500; x += 10) {
  context.moveTo(x, 0.5)
  context.lineTo(x, 1.5)
}

【问题讨论】:

    标签: html canvas


    【解决方案1】:

    谢谢米奇。我还找到了一些解释:

    https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Applying_styles_and_colors#A_lineWidth_example

    这是相关内容:

    要获得清晰的线条,需要了解路径的描边方式。在 下图中,网格代表画布坐标网格。这 网格线之间的正方形是实际的屏幕像素。在第一 下面的网格图像,填充了从 (2,1) 到 (5,5) 的矩形。这 它们之间的整个区域(浅红色)落在像素边界上,所以 生成的填充矩形将具有清晰的边缘。

    如果您考虑从 (3,1) 到 (3,5) 的路径,其线宽为 1.0,您最终会遇到第二张图片中的情况。要填充的实际区域(深蓝色)仅延伸到像素的一半 路径的任一侧。必须渲染一个近似值, 这意味着这些像素仅被部分着色,并且结果 在整个区域(浅蓝色和深蓝色)被填充 一种颜色只有实际笔触颜色的一半。这是什么 发生在前面示例代码中的 1.0 宽度线。

    要解决此问题,您必须非常精确地创建路径。 知道 1.0 宽度的线将向任一侧延伸半个单位 的路径,创建从 (3.5,1) 到 (3.5,5) 的路径导致 第三幅图像中的情况——1.0 线宽完全结束, 精确填充单个像素垂直线。

    【讨论】:

    • 这个链接解释了问题和解决方案。
    【解决方案2】:

    我不确定它是否与 HTML5 相同,但它看起来与 Qt 库处理绘画的方式非常相似。本质上,(0,0) 和 (1,1) 坐标定义了左上角的像素 - 因此其中心位于 (0.5, 0.5)。

    这与抗锯齿有关 - 如果您在 (1,1) 处“绘制”一个黑色像素,则在 (0,0) 和 (2,2) 之间的 4 个灰色像素实际上将被绘制为灰色。在C++ GUI programming with Qt 4 中了解更多信息。

    【讨论】:

      【解决方案3】:

      简而言之,像素是无法分割的。当您使用 lineTo 绘制 1 像素线时,该线以您指定的坐标为中心。如果 width=1 且坐标是整数,那么您要求绘制 2 个像素的一半。

      由于您无法打开半个像素,因此库会四舍五入到两侧最近的可整像素。

      【讨论】:

        【解决方案4】:

        当我在一段时间后再次使用画布开始时,我或多或少会与之抗争——你正在使用“数学”线条而不是屏幕上的线条。

        正如其他人提到的 - 从 (1,1) 到 (1,10) 的线开始于像素 (0/0, 1/1) 之间并结束于 (0/10, 1/11) 之间

        所以它的宽度为 1 像素,高度为 1 像素。但是稍微轻一点...

        我的解决方案,如果您使用画布仅绘制“硬 - 整数 - 线”,例如要创建一个控件,是使用transform(1,0,0,1,0.5,0.5)(或transform(1,0,0,1,-0.5,-0.5),取决于你想用0还是1开始)

        (我使用变换来确定,没有(a)或(d)再次让我的生活变得艰难)

        只需在“0 和 1 之间”的行上移零(现在你知道我的昵称了...)

        这在我绘制(或必须绘制)“像素化”的所有情况下都可以正常工作

        【讨论】:

          猜你喜欢
          • 2010-12-01
          • 1970-01-01
          • 1970-01-01
          • 2019-06-01
          • 2015-09-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-09-07
          相关资源
          最近更新 更多