Как нарисовать пиксельный шрифт на холсте без сглаживания

#javascript #canvas #text #fonts #antialiasing

Вопрос:

У меня есть пиксельный шрифт (в файле ttf), я обнаружил, что его собственное разрешение составляет 8 пикселей ( CTX.font = '8px mainfont'; )

Когда я заполняю текст, шрифт получается идеальным в firefox, но размытым в chrome:

введите описание изображения здесь браузер Firefox

хром хром

Я попытался компенсировать координату X разными величинами, например 0,5, но она просто становится более размытой. Обычно это всегда круглое целое число.

Я попытался CTX.translate(0.5, 0); и CTX.imageSmoothingEnabled = true;

Я попробовал css font-smooth: none; font-smooth: never; -webkit-font-smoothing : none;

В прошлом мне приходилось конвертировать свои шрифты в специальный формат и использовать библиотеку для их рисования на холсте. Просто надеялся, что 5 лет спустя они добавили официальный способ решения этой проблемы?

Ответ №1:

Просто надеялся, что 5 лет спустя они добавили официальный способ решения этой проблемы?

Хорошо… не более нескольких месяцев назад в API canvas было добавлено больше текстовых модификаторов, среди которых ctx.textRendering , в основном , эквивалент SVG text-rendering .

Таким образом, ни один из вариантов на самом деле не заставит отключить сглаживание, но при использовании вы, безусловно, получите лучшие результаты textRendering = "geometricPrecision" .

Кроме того, в настоящее время это поддерживается только браузерами на базе Chromium … и только при chrome://flags/#enable-experimental-web-platform-features включенном.

 const label = document.querySelector( "label" );
const canvas = document.querySelector( "canvas" );
const ctx = canvas.getContext( "2d" );
if( !ctx.textRendering ) {
  console.warn( `Your browser doesn't support the textRendering property on Canvas
If you are on Chrome be sure to enable chrome://flags/#enable-experimental-web-platform-features` );
}

let state = 0;
const states = [
  () => {
    label.textContent = "optimizeLegibility";
    ctx.textRendering = "optimizeLegibility";
    drawText();
  },
  () => {
    label.textContent = "geometricPrecision";
    ctx.textRendering = "geometricPrecision";
    drawText();
  },
  () => {
    label.textContent = "difference";
    ctx.textRendering = "optimizeLegibility";
    drawText();
    ctx.globalCompositeOperation = "xor";
    ctx.textRendering = "geometricPrecision";
    drawText();
    ctx.globalCompositeOperation = "source-over";
  }
];

document.fonts.load( "120px pixel" ).then( begin );

function begin() {
  
  ctx.clearRect( 0, 0, canvas.width, canvas.height );
  ctx.font = "120px pixel";
  states[ state ]();
  state = (state   1) % states.length;
  setTimeout( begin, 1000 );
  
} 
function drawText() {
  ctx.textBaseline = "top";
  ctx.fillText( "TESTING", 0, 0 );
} 
 @font-face {
  font-family: pixel;
  src: url("https://dl.dropboxusercontent.com/s/hsdwvz761xqphhb/pixel.ttf");
} 
 <label></label><br>
<canvas width="500"></canvas> 

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