html - Chrome 上的小型 HTML5 Canvas 上没有子像素定位

标签 html google-chrome canvas subpixel

在大 Canvas 上制作图像动画时,图像在非整数坐标上正确渲染,并且动画流畅。 在小 Canvas 上,例如 200x200,子像素坐标不适用,并且图像从整数位置“跳跃”到下一个位置,从而产生“抖动”运动。

该问题似乎仅适用于光栅源(图像和 Canvas )。例如,文本在所有 Canvas 尺寸上都能流畅地呈现动画。

我目前正在使用 Chrome 版本 58.0.3029.110(64 位)进行测试,但早期版本中也出现了该问题。

有人偶然发现这个问题吗?

这是我测试的代码:

<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
<script>
    var outer = [200, 200];
    var inner = [200, 200];

    function CreateCanvas(w, h, hidden) {
        var canvas = document.createElement('canvas');
        if(!hidden) document.body.appendChild(canvas);
        canvas.width = w;
        canvas.height = h;
        var context = canvas.getContext('2d');
        return {canvas:canvas, context:context};
    }

    function rgba2hex(color) {
        return "rgba(" + Math.floor(color[0] * 255) + ',' + Math.floor(color[1] * 255) + ',' + Math.floor(color[2] * 255) + ',' + color[3] + ")";
    }

    function GetSystemTimeMS() {
        return (new Date()).getTime();
    }

    function GetTimeDifferenceMS(time) {
        return GetSystemTimeMS() - time;
    }

    var outerFontSize = Math.min(100, outer[1] * 0.3);
    var innerFontSize = Math.min(100, inner[1] * 0.3);

    var outerBuffer = CreateCanvas(outer[0], outer[1], false);
    outerBuffer.context.font = outerFontSize + "px times";
    outerBuffer.context.fillStyle = rgba2hex([0,0,0,1]);    

    var innerBuffer = CreateCanvas(inner[0], inner[1], true);
    innerBuffer.context.font = innerFontSize + "px times";
    innerBuffer.context.fillStyle = rgba2hex([0,0,0,1]);
    innerBuffer.context.fillText("raster", 10, inner[1] * 0.9);

    var startTime = GetSystemTimeMS();
    function draw() {
        var span = 5;
        var phase = ((GetTimeDifferenceMS(startTime) / 1000) % span) / span;
        outerBuffer.context.clearRect(0, 0, outer[0], outer[1]);
        var x = 50 + phase * 20;

        outerBuffer.context.fillText("vector", x, outer[1] * 0.5);
        outerBuffer.context.drawImage(innerBuffer.canvas, x, 0);

        window.setTimeout(draw, 10);
    }
    draw();
</script>
</body>
</html>

最佳答案

我绝对可以在我的稳定版 chrome 和我的 Canary 上重现它。
I reported给 Chrome 团队。希望修复能够尽快到来。

作为解决方法,您可以稍微缩小图像(我发现的最小值是 size * 0.99。这应该会强制启动抗锯齿算法。

var outer = [200, 200];
var inner = [200, 200];

function CreateCanvas(w, h, hidden) {
  var canvas = document.createElement('canvas');
  if (!hidden) document.body.appendChild(canvas);
  canvas.width = w;
  canvas.height = h;
  var context = canvas.getContext('2d');
  return {
    canvas: canvas,
    context: context
  };
}

function rgba2hex(color) {
  return "rgba(" + Math.floor(color[0] * 255) + ',' + Math.floor(color[1] * 255) + ',' + Math.floor(color[2] * 255) + ',' + color[3] + ")";
}

function GetSystemTimeMS() {
  return (new Date()).getTime();
}

function GetTimeDifferenceMS(time) {
  return GetSystemTimeMS() - time;
}

var outerFontSize = Math.min(100, outer[1] * 0.3);
var innerFontSize = Math.min(100, inner[1] * 0.3);

var outerBuffer = CreateCanvas(outer[0], outer[1], false);
outerBuffer.context.font = outerFontSize + "px times";
outerBuffer.context.fillStyle = rgba2hex([0, 0, 0, 1]);

var innerBuffer = CreateCanvas(inner[0], inner[1], true);
innerBuffer.context.font = innerFontSize + "px times";
innerBuffer.context.fillStyle = rgba2hex([0, 0, 0, 1]);
innerBuffer.context.fillText("raster", 10, inner[1] * 0.9);

var startTime = GetSystemTimeMS();

function draw() {
  var span = 5;
  var phase = ((GetTimeDifferenceMS(startTime) / 1000) % span) / span;
  outerBuffer.context.clearRect(0, 0, outer[0], outer[1]);
  var x = 50 + phase * 20;

  outerBuffer.context.fillText("vector", x, outer[1] * 0.5);
  // shrink a little bit our image
  outerBuffer.context.drawImage(innerBuffer.canvas, x, 0, 200 * 0.99, 200 * 0.99);

  requestAnimationFrame(draw);
}
draw();

关于html - Chrome 上的小型 HTML5 Canvas 上没有子像素定位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44323932/

相关文章:

javascript - 文本区域是必填字段吗?

javascript - 带有按钮和图像的工具提示

android - 全息进度条发光效果

javascript - 在模态窗口中打开图像

jquery - Bootstrap 正在向 JQTree 添加冲突的样式

javascript - 隐藏提取错误

javascript - 仅在 Chrome 中(服务 worker ): '... a redirected response was used for a request whose redirect mode is not "follow"'

javascript - 如何在 Chrome 时间轴中命名匿名函数?

javascript - 在 javascript 数组中绘制读取值的问题 - 在 HTML5 Canvas 中绘制

javascript - 在 Canvas 中绕原点旋转一个点