Ограничительная рамка текста SVG отличается от браузера к браузеру при использовании @font-face?

Я пытаюсь разместить текстовый элемент SVG в соответствии с шириной и высотой текста, получив ограничивающую рамку с помощью метода getBBox().

Если в тексте используется безопасный веб-шрифт, это работает достаточно хорошо в разных браузерах, но если текст оформлен с использованием @font-face и пользовательского веб-шрифта, ширина текста возвращается неправильно в Firefox (Mac) и Safari ( iOS). Он отлично работает как в Safari (Mac), так и в Chrome (Mac).

Если серое поле имеет ту же ширину, что и текст, то оно работает в этом браузере.

Кто-нибудь знает, как получить правильную ширину рамки текста во всех браузерах?


person Mads Buch Stage    schedule 20.09.2012    source источник


Ответы (2)


Браузер вычисляет BBox до завершения загрузки/применения @font-face, попробуйте...

onreadystatechange="if(document.readyState == "complete"){init()}"

document.readyState срабатывает в трех состояниях: loading (когда страница загружается), interactive (когда она закончила синтаксический анализ, но все еще загружает ресурсы) и complete (когда браузер действительно завершен), поэтому вы просто добавляете условие для выполнения init(), когда document.readyState полный.

person methodofaction    schedule 20.09.2012
comment
Спасибо за предложение! На самом деле у меня была точно такая же мысль ранее сегодня, поэтому я уже добавил этот тест в пример, и он работает! - person Mads Buch Stage; 21.09.2012

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

Проблема в WebKit (проверено в Chrome 24.0.1312.52 и 26.0.1389.0 canary) заключается в том, что браузер откладывает загрузку внешнего шрифта до тех пор, пока он впервые не будет эффективно использован где-либо на странице. Таким образом, даже если вы ждете, пока onreadystatechange станет «завершенным», вам не гарантируется, что метрики шрифта будут готовы при вызове getBBox() — вы все равно можете быть первым, кто отобразит текст, стилизованный под внешний шрифт, вставит его в документ и немедленно вызовет getBBox() на нем (мой случай).

Мой обходной путь вместо прямого вызова mySVGInitCode() я делаю:

$("body").append(
  $("<div/>")
    .attr("class", "force-external-font-loading")
    .attr("style", "font-family: \"xkcd\";visibility:hidden;position:absolute")
    .text("x")
  );
setTimeout(function(){ mySVGInitCode() }, 100); // 100ms is just arbitrary waiting time which should be sufficient for fetching the external font on a fast network, anyone has a better solution?

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

person Antonin Hildebrand    schedule 22.01.2013