Нет субпиксельного позиционирования на небольшом холсте HTML5 на Chrome
При анимации изображения на большом холсте изображение отображается правильно по нецелым координатам, а анимация плавная. на небольшом холсте, скажем, 200x200, субпиксельные координаты не применяются, и изображение "перепрыгивает" из целочисленного положения на следующее, создавая "дрожащее" движение.
проблема, кажется, относится только к растровым источникам (изображениям и холстам). текст, например, плавно анимируется на всех размерах холста.
В настоящее время я тестирую с версией 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>
1 ответ
Я точно могу воспроизвести его как на своем стабильном хроме, так и на своей канарейке.
Я доложил команде хрома. Будем надеяться, что исправление придет достаточно скоро.
В качестве обходного пути вы можете немного уменьшить свои изображения (минимальное значение, которое я нашел, было 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();