0

我有一个带有鼠标悬停事件的简单画布。当用户移动鼠标时,我想在事件的 x,y 坐标处绘制一个像素(将来它会比单个像素更复杂)。本质上它就像一个自定义光标。

逻辑非常简单,如下所示。奇怪的是,虽然我正在清理旧的像素位置,但仍有微小的像素残留物(自从我发布这个问题以来,我发现它与 Retina 显示器有关)。我已经能够解决这个问题。我不是保存 1px 并恢复 1px,而是保存 3px 并恢复 3px。但我不明白为什么我需要这样做,并且将来当我绘制更复杂的光标时,我希望脏像素处理是精确的。

这是一个可运行的 JSFiddle 示例:http: //jsfiddle.net/sbCq3/2/

// cleanup previously drawn pixel
ctx.putImageData(lastImageData, lastImageX, lastImageY);

// save the imageData currently at x,y
lastImageData = ctx.getImageData(x, y, 1, 1);
lastImageX = x;
lastImageY = y;

// draw the dot
var dotData = ctx.createImageData(1, 1);
...
ctx.putImageData(dotData, x, y);

我有点难过。我想知道这是否与我的 Retina 显示器有关。如果我在 5,5 处绘制单个像素,它是图像数据中的单个像素 - 但我可以使用 DigitalColor Meter(内置缩放工具)进行缩放,并看到单个像素被细分和抗锯齿。而如果我在 Windows 机器上查看该像素,则它是一个不错的实心像素。我还没有测试过这个问题是否出现在 Windows 或非视网膜机器上。(我不是指正常的画布抗锯齿问题)。


更新:我刚刚在我的同事非视网膜 MacBook 17" 上进行了测试,它工作得非常好。所以这肯定与 Retina 显示器有关。

4

1 回答 1

0

我不完全确定,但我认为这可能与不同屏幕的分辨率有关。如果您曾经在智能手机上查看过 html5 画布,其每平方英寸的分辨率大多数都比显示器高得多,那么您会发现质量下降很多,因为网络浏览器会扩展您告诉它的 100 像素使用相同的物理尺寸,最终约为 130 像素。我认为你的视网膜显示器也会发生同样的情况,因为它使用了非常好的分辨率。基本上,不同的屏幕具有不同的像素大小比例。为了解决这个问题,我在我的代码中添加了以下内容。

var PIXEL_RATIO = (function() {
  var ctx = document.createElement("canvas").getContext("2d"),
      dpr = window.devicePixelRatio || 1,
      bsr = ctx.webkitBackingStorePixelRatio ||
            ctx.mozBackingStorePixelRatio ||
            ctx.msBackingStorePixelRatio ||
            ctx.oBackingStorePixelRatio ||
            ctx.backignStorePixelRatio || 1;

  return dpr / bsr;
  })();

现在,无论何时制作画布或绘制任何东西,都将常量乘以变量 PIXEL_RATIO。

于 2013-08-05T15:03:38.730 回答