Дробные размеры шрифта html5 canvas?
У меня проблема с тем, как разные браузеры отображают размеры шрифтов на холсте HTML5. Разработан, где размер шрифта не являются целыми числами. Например "8.5 px Arial", "2.23 em Arial" и так далее.
для холста.font= FontSize + "px Arial"; где FontSize (8.1, 8.2, 8.3,...) Я ожидал бы линейного результата, однако единственный браузер, который последовательно архивирует это IE ! ( Я знаю ). В Firefox туров ниже 11.2 px а линейная дальше. Только Chrome и Safari масштабируйте шрифты до целочисленных значений.
правило округления, похоже, установлено в пиксели и округляется до ближайшего целого числа ниже .5
мое приложение canvas выполняет некоторые программные анимированные преобразования ( масштабирование и перевод), пытаясь избежать преобразований canvas ради эффективности, хотя я подозреваю, что это решит проблему, я также не тестировал это, установив размер текста html только с CSS3 (что холст.предполагается, что шрифт основан на spec)
браузеры, по крайней мере, согласованы в поведении между размерами шрифтов pt, px, em и%. [edit: кроме Safari не отображает размеры%]
[ в сторону: все шрифты выглядят немного полужирными, когда они немного увеличены. Safari берет этот торт, когда мы идем от 17.4 px до 17.5 px .. БЭМБ!]
Я приложил несколько примеров изображений ниже, но мне бы очень хотелось, чтобы некоторые идеи о том, как сделать все браузеры более похожими на IE (снова никогда не думал, что скажу это) - это ошибка или стандартных шрифтов?
вот мой тестовый код, который можно реплицировать для случая размера шрифта PX.
<!DOCTYPE html><html><head><script>
function display() {
var canvas = document.getElementById('test');
// For EM and % cases....
//canvas.style.font="5px Arial";
canvas.height = 1000;
var context = canvas.getContext('2d');
var minSize = 10;
var lineHeight = 100;
for(var a=minSize; a< 20; a+=0.1)
{
var font_size = Math.round(a*10000)/10000;
context.font = a + "px Arial";
context.fillText("A: EXAMPLE TEXT > " + font_size, 20, (font_size-minSize)*lineHeight);
}
}
</script></head><body onload="display()"><canvas id="test"></canvas></body></html>
шкала пиксель Точечная шкала шкала em-1em = 5px Arial процентная шкала-100% = 5px Arial
1 ответов
Я думал, что вы должны были сделать мою работу за меня ;) в любом случае, вот как я решил проблему, хотя это немного взломать и все еще есть некоторые проблемы, которые я опишу.
чтобы повторить (потому что это было неясно в вопросе, возможно), я пытался умножить размеры шрифта на некоторое число с плавающей запятой, чтобы увеличить и уменьшить текст. Но это привело к нервным результатам из-за того, что большинство округляет размер шрифта до ближайшего целочисленного значения.
Так для пример.
var zoom = 1.02;
var font_size = 12;
context.font = (font_size * zoom) + "px Arial"; // 12.24px
zoom = 1.04 (12.48 px) будет отображаться так же, как и приведенный выше код, а zoom =1.06 (12.75 px) будет округлен до 13px.
это привело к очень нежелательному скачку размера шрифта между значениями, в то время как все остальные элементы на холсте были масштабированы правильно.
проблема усугублялась тем, что все браузеры отображают заданную строку текста, такую как "пример текста", и немного разные длины.
в решение
во время инициализации визуализируйте текст со стандартным размером шрифта (zoom=1) и измерьте длину строки, пусть это значение будет называться iniLineLength
во время рендеринга сцены я использовал скрытый холст для рендеринга текста, а затем использовал drawImage для основного холста с множителем по ширине.
tmpContext.font = (font_size * zoom) + "px Arial";
tmpContext.fillText(MyLineOfText,0, 0);
var s = (iniLineLength * zoom) / tmpContext.measureText(MyLineOfText) ;
mainContext.drawImage(tmpCanvas,x, y, pw * s, ph);
результирующая строка текста растягивается или сжимается на основном холсте в зависимости от того, как далеко длина строки от ожидаемой длины строки.
в идеальном мире s всегда будет равен единице, так как ожидаемая длина линии всегда будет такой же, как фактическая длина линии. Ожидаемая длина строки-это длина линии выборки iniLineLength, умноженная на тот же коэффициент масштабирования, что и размер шрифта в этом проходе рендеринга.
Я бонус ко всему этому заключается в том, что он имеет эффект нормализации всех различий в поведении браузера... почти.
вопросы
даже при нормализованной длине линии точное положение каждого символа в строке не совпадает. Давая эффект на изображении ниже.
однако это уже значительное улучшение по сравнению с тем, что у меня было.
кроме того, вы захотите обрезать свои tmpCanvas на mainCanvas, иначе ваш браузер остановится, когда он попытается создать и скопировать текст на мега-пиксели, просто ради того, чтобы иметь один символ в полноэкранном режиме.
имея это в виду, вы можете также установите ширину и высоту холста tmp в соответствии с фактической строкой текста, которую вы собираетесь визуализировать, это сэкономит память, время и так далее.