HTML5 текстовые сглаживания холста в chrome, а не в firefox

1

Я рисую пользовательский моноширинный бит-шрифт на холст HTML5 с помощью JavaScript, и у меня разные результаты между Firefox и Chrome. Firefox рисует его так, как я его предпочитаю:

Изображение 174551

Хотя Chrome привлекает его с помощью сглаживания, что я не могу понять, как избавиться:

Изображение 174551

HTML-код с CSS и JavaScript для воспроизведения проблемы следующий. (Загрузка шрифта).

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <style>
        @font-face {
            font-family: tis-100-copy;
            src: local("tis 100 copy"),
                local("tis-100-copy"),
                url(tis100copy.ttf);
            font-weight: bold;
        }

        html {
            position: relative;
            background-color: #DDDDDD;
            font-family: tis-100-copy;
        }
        canvas#game {
            position: relative;
            padding-left: 0;
            padding-right: 0;
            margin-left: auto;
            margin-right: auto;
            display: block;
        }
    </style>
</head>
<body>
    <canvas id="game" width="1366" height="768"></canvas>
    <script>
        var canvas = document.getElementById("game");
        var ctx = canvas.getContext("2d");

        //ctx.translate(0.5, 0.5); // Just causes both browsers to anti-alias

        ctx.mozImageSmoothingEnabled = false;
        ctx.webkitImageSmoothingEnabled = false;
        ctx.msImageSmoothingEnabled = false;
        ctx.imageSmoothingEnabled = false;
        ctx.font = "12pt tis-100-copy";

        function gameLoop() {

            ctx.beginPath();
            ctx.fillStyle = "#000000";
            ctx.fillRect(0, 0, canvas.width, canvas.height);

            ctx.fillStyle = "#FFFFFF";
            ctx.fillText("ThE qUiCk BrOwN fOx JuMpS oVeR tHe LaZy DoG.", 50, 50);
            ctx.fillText("1234567890", 50, 62); 
            ctx.fillText("!#%()+,-./:<=>?[\\]_", 50, 74);

            requestAnimationFrame(gameLoop);
        }
        requestAnimationFrame(gameLoop);
    </script>
</body>
</html>

Как я могу заставить Chrome чисто нарисовать текст без сглаживания?

  • 0
    Вы пытались использовать пиксели, а не точки. например, ctx.font = "12px tis-100-copy";
  • 0
    Чтобы получить текст такого же размера, мне пришлось использовать 16 пикселей, и нет, это не решило проблему.
Показать ещё 1 комментарий
Теги:
canvas
html5-canvas
cross-browser

2 ответа

1
Лучший ответ

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

Вы можете преобразовать соответствующий шрифт в спрайт-лист, а затем создать простую пользовательскую функцию для визуализации текста.

Процесс прост и производительность более чем достаточна, если нет большого количества текста, который нужно визуализировать.

Основы

Вот пример:

  • Шрифт преобразуется в растровый шрифт, в основном однострочный спрайт-лист, оптимизированный по размеру (и преобразованный здесь в data-uri).
  • Важно: при сгенерировании генерируются только символы ASCII из и включая 32 (пробел), вплоть до char 128.
  • Создается пользовательская функция для анализа каждого символа в строке. Символ преобразуется в индекс ASCII, а 32 вычитается, поскольку мы пропустили это при создании спрайта.
  • Рассчитывается область в справочном листе, а затем отображается непосредственно на холст в текущей позиции (x + string-index * width-width, y as-is).

// Note: font sprite-sheet premade using: 
//   https://jsfiddle.net/epistemex/bdm3tbtu/
var ctx, cw = 8, ch = 19, img = new Image; img.onload = go; img.src = bmp;
function go() {
  ctx = c.getContext("2d");
  // Custom text drawing function demo:
  myFillText(ctx, "My custom text fill function", 12, 8);
};

function myFillText(ctx, str, x, y) {
  x |= 0; y |= 0; // force x/y to integer positions
  for(var i = 0, ascii; i < str.length; i++) {
    // get ASCII code but offset -32 to match sprite-sheet
    ascii = str.charCodeAt(i) & 0xff - 32;
    // look-up bitmap font sprite-sheet and draw directly to canvas
    ctx.drawImage(img, ascii * cw, 0, cw, ch, x + i * cw, y, cw, ch);
  }
}
<canvas id=c width=600></canvas>
<script>
var bmp = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAvgAAAATBAMAAAAXEGS4AAAAG1BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACUUeIgAAAACHRSTlMAljxY3CJ2uKuwIxoAAANySURBVFjD7VhNa9tAEH2SZUlH0ULPatJSH00/IEdBc8jREAg6OqSBHg29+LiR43R+djMfm9VXKKREDcRPrFc7mtGbeVptNsIBBxxwwP/GrMQBEyO53kNAt1BsdydoISrwPJgRbTA9Eq2nnpS7LiKWct/P5dte+6ujSsWu6q/t628vKzwH4htgUWJyfL7W3mE6xA0ioFcvAVnpkDtCfVwWYGRF8sku5pzg6RnGkBMBOfeOm/gT28hx77w9gDTOQe0f2FRZDIEsjpuMmZ/UmVx+b9eMuBkHfJ9bb4f52WG5CDimiCA4lpQm4Ue0QaTatgRkOwq95fcSgqz6deFVIkt4CEsCD3TI5ZetHfJA5gWA2ivURHf3Zj2srDASRw1QC8AyELyv9ebrKB8vHiSxzshnZbpq1T8JP1Kn4ifrrvgMfjoxLTkImFF5tgO8ksm7y4r7DvTmNhvIFPVnXfGZO9uL0YfKIC3jHTWhFD0gAhD6xXPTPGlQevAdKZ7V1FgTPwIKGAjT8GNm4ufLgfjiiuRGxVqcol6ZRjyOChsECI28a+jJHRYXckH8sNyYR87J5Oswj+DLBzceP1o8jRWPQfGSnnIpt9XzBrgKVUzDj2yt4qebjoZB/NnPDTumm5PlF4RkbX3XEQUlKecfczQivqwuZH8LqE9lwcAFfoAKEp+H4imMiVrFkwgonCIA1JfgY7rFW24S5+v392qDMA3/vIGKj8VqQev5iPhHDY/rMtkXPfFtYDAiYoJQFCdl9PZwtGcMZj4B57gD0WMzjzqvsl+P5Sy34pXtvheeQfFBeGnhCQRMxo9kqeLHFQpsb/tJuIvZx4YdT8pYL2pGI+IbF9NTeEi+tZM2RyNB517n8+axNVesw+L1l9AqPqfhmmv+ZhPROjkGTMbfX/MHM78+f19xwKKKaZN5hdu+zvdiHux2tO+Ir+beAyRt6XyXUUojuw2gX1DwCDLYmzT0JdcpXj00gaH4k/D/Xfw53YLVTOl3THuYvOPiOygxSQv7Ye7966bnECRNe59v4mPb0B0th/tsgAdWiDRyYa0N+2zAXnzlDdziZfHtfT4PBuJPwY+osq1m8aRvO0z5dKQjdDIJMvwLpLonQARRTMLf/idrcmRjKb7RyfgqMN+p+CcrvAxkFbDFK0GuH9ZezlyriV7RV+wIAX8AnAnL3b7xqFYAAAAASUVORK5CYII=";
</script>

Как иметь дело с разными цветами (или градиентами, узорами)

Можно сделать пару простых модификаций, позволяющих использовать цвета, градиенты, рисунки и т.д.

  • Создайте внеэкранный холст того же размера, что и спрайт-лист
  • Нарисуйте изображение
  • Выберите режим композиции "source-atop", выберите цвет (или градиент, рисунок) и заполните весь экранный холст. Теперь продолжайте, как раньше, но используйте экранное изображение как источник изображения вместо самого изображения.

// Note: font sprite-sheet premade using: 
//   https://jsfiddle.net/epistemex/bdm3tbtu/
var cw = 8, ch = 19, c2, img = new Image; img.onload = go; img.src = bmp;
var ctx = c.getContext("2d"), ctx2;
function go() {
  // setup offscreen-canvas
  c2 = document.createElement("canvas");
  c2.width = this.width; c2.height = this.height;
  ctx2 = c2.getContext("2d");
  ctx2.drawImage(this, 0, 0);
  
  myFontColor("#c00");
  myFillText(ctx, "My custom text fill function in red...", 12, 8);
};

function myFontColor(style) {
  ctx2.globalCompositeOperation = "source-atop";
  ctx2.fillStyle = style;
  ctx2.fillRect(0, 0, c2.width, c2.height);
}

function myFillText(ctx, str, x, y) {
  x |= 0; y |= 0;
  for(var i = 0, ascii; i < str.length; i++) {
    ascii = str.charCodeAt(i) & 0xff - 32;
    ctx.drawImage(c2, ascii * cw, 0, cw, ch, x + i * cw, y, cw, ch);
  }
}
<canvas id=c width=600></canvas>
<script>
var bmp = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAvgAAAATBAMAAAAXEGS4AAAAG1BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACUUeIgAAAACHRSTlMAljxY3CJ2uKuwIxoAAANySURBVFjD7VhNa9tAEH2SZUlH0ULPatJSH00/IEdBc8jREAg6OqSBHg29+LiR43R+djMfm9VXKKREDcRPrFc7mtGbeVptNsIBBxxwwP/GrMQBEyO53kNAt1BsdydoISrwPJgRbTA9Eq2nnpS7LiKWct/P5dte+6ujSsWu6q/t628vKzwH4htgUWJyfL7W3mE6xA0ioFcvAVnpkDtCfVwWYGRF8sku5pzg6RnGkBMBOfeOm/gT28hx77w9gDTOQe0f2FRZDIEsjpuMmZ/UmVx+b9eMuBkHfJ9bb4f52WG5CDimiCA4lpQm4Ue0QaTatgRkOwq95fcSgqz6deFVIkt4CEsCD3TI5ZetHfJA5gWA2ivURHf3Zj2srDASRw1QC8AyELyv9ebrKB8vHiSxzshnZbpq1T8JP1Kn4ifrrvgMfjoxLTkImFF5tgO8ksm7y4r7DvTmNhvIFPVnXfGZO9uL0YfKIC3jHTWhFD0gAhD6xXPTPGlQevAdKZ7V1FgTPwIKGAjT8GNm4ufLgfjiiuRGxVqcol6ZRjyOChsECI28a+jJHRYXckH8sNyYR87J5Oswj+DLBzceP1o8jRWPQfGSnnIpt9XzBrgKVUzDj2yt4qebjoZB/NnPDTumm5PlF4RkbX3XEQUlKecfczQivqwuZH8LqE9lwcAFfoAKEp+H4imMiVrFkwgonCIA1JfgY7rFW24S5+v392qDMA3/vIGKj8VqQev5iPhHDY/rMtkXPfFtYDAiYoJQFCdl9PZwtGcMZj4B57gD0WMzjzqvsl+P5Sy34pXtvheeQfFBeGnhCQRMxo9kqeLHFQpsb/tJuIvZx4YdT8pYL2pGI+IbF9NTeEi+tZM2RyNB517n8+axNVesw+L1l9AqPqfhmmv+ZhPROjkGTMbfX/MHM78+f19xwKKKaZN5hdu+zvdiHux2tO+Ir+beAyRt6XyXUUojuw2gX1DwCDLYmzT0JdcpXj00gaH4k/D/Xfw53YLVTOl3THuYvOPiOygxSQv7Ye7966bnECRNe59v4mPb0B0th/tsgAdWiDRyYa0N+2zAXnzlDdziZfHtfT4PBuJPwY+osq1m8aRvO0z5dKQjdDIJMvwLpLonQARRTMLf/idrcmRjKb7RyfgqMN+p+CcrvAxkFbDFK0GuH9ZezlyriV7RV+wIAX8AnAnL3b7xqFYAAAAASUVORK5CYII=";
</script>

Некоторая оптимизация может быть получена, например, с помощью общих слов prerender в отдельный спрайт-лист, а затем обнаруживать это в пользовательской текстовой функции.

  • 0
    Определите «большое количество текста». На экране может быть до 4000 символов одновременно. (Мне нужно только перерисовать, в среднем, несколько десятков каждого кадра.) -
  • 1
    @TakingItCasual 4000 должен работать (на кадр), но у меня нет теста производительности (я основываю его на создании системы частиц несколько лет назад, которая могла бы производить более 10 000 спрайтов, включая изменение размера, сглаживание и т. Д.); вам придется сделать один - вы в любом случае заметите, когда вы закроете лимит (и создадите некоторый резервный буфер для этого, так как он будет отличаться от компьютера к компьютеру). Если предполагается, что один и тот же текст будет отображаться в течение некоторого периода времени, я бы рекомендовал вместо этого кэшировать текст на внеэкранном холсте и просто рисовать этот холст поверх одной операции рисования до следующего изменения.
0

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

  • 0
    Я уже применил многие решения из этой темы. Они не решили проблему. Я добавил ссылку для шрифта.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню