Зубчатый текст при заполнении текста на холсте в Chrome

Я пытаюсь нарисовать текст на холсте, но нарисованный текст имеет неровности, особенно в Chrome 31.0.1650. я пытался -webkit-font-smoothing:antialiased,text-shadow но все идет напрасно.

Как решить эту проблему? Заранее спасибо.

Вот код стиля:

<style>
    #my_canvas{           
        -webkit-font-smoothing: antialiased;
        text-shadow: 1px 1px 1px rgba(0,0,0,0.004);
        text-indent: -9999px; 
    }                   
</style>

Код в теле:

<canvas id="my_canvas" height="300" width="2200"></canvas>
<script>
    var canvas = document.getElementById("my_canvas");
    var context = canvas.getContext("2d");
    context.imageSmoothingEnabled =true;
    context.fillStyle = "BLACK";
    context.font = "bold 100px Arial";
    context.fillText("A quick brown fox jumps over the lazy dOg", 50, 200);
</script>

1 ответ

Решение

Это проблема с текстовым движком Chrome.

Есть способ, который вы можете использовать, чтобы обойти это, хотя:

  • Установите холст за пределами экрана в два раза больше холста на экране
  • Нарисуйте текст на внеэкранном холсте в масштабе: размер шрифта и положение
  • Нарисуйте холст за пределами экрана, чтобы уменьшить масштаб основного холста (в данном случае это половина).

Живая демо здесь

Разница невелика (как и ожидалось), но улучшает качество. Вот расширение:

сравнить

Sidenotes: CSS не влияет на содержание холста, только на элементы. Сглаживание изображений включено по умолчанию и влияет только на изображения, но не на текст или фигуры (мы будем использовать это для этой техники).

var scale = 2;  // scale everything x2.

var ocanvas = document.createElement('canvas');
var octx = ocanvas.getContext('2d');

ocanvas.width = canvas.width * scale;   // set the size of new canvas
ocanvas.height = canvas.height * scale;

// draw the text to off-screen canvas instead at double sizes
octx.fillStyle = "BLACK";
octx.font = "bold " + (100 * scale) + "px Arial";
octx.fillText("A quick brown fox jumps over the lazy dOg", 50*scale, 200*scale);

// key step is to draw the off-screen canvas to main canvas
context.drawImage(ocanvas, 0, 0, canvas.width, canvas.height);

Что происходит, так это то, что мы вводим интерполяцию в миксе. Chrome будет рисовать текст очень грубо и за пределами экрана, но после того, как текст будет растеризован, мы можем работать с ним как с изображением.

Когда мы рисуем холст (он же изображение) на нашем основном холсте с половиной размера, включается интерполяция (субсэмплинг) и фильтрует нижние частоты пикселей, обеспечивая более плавный вид.

Это, конечно, потребует больше памяти, но если важен результат, это небольшая цена, которую нужно платить в настоящее время.

Вы, вероятно, заметите, что другие значения, кроме 2, работают не так хорошо. Это связано с тем, что холст обычно использует билинейную интерполяцию, а не бикубику (что позволило бы нам использовать 4). Но я думаю, что 2х хорошо нам в этом деле.

Почему бы не использовать преобразование, т.е. scale()? Текстовый движок Chrome (или способ его использования) не растеризует текст в 1x, а затем преобразует его. Он берет векторы, преобразует их, а затем растеризует текст, что даст тот же результат (т. Е. Масштаб 0,5, нарисуйте дважды).

Другие вопросы по тегам