На этой неделе в очередной раз столкнулся с проблемой «нестандартных» шрифтов, и если ранее можно было иногда обойтись самой обычной нарезкой в графическом редакторе или использовать какие-то клиентские приёмы подмены, то в этот раз задача стоит наиболее глобально. Динамических заголовков в надвигающемся проекте реально много.
Своими мыслями, поиском и конечным решением я и хотел бы поделиться с вами.
Итак, в принципе, какие у нас есть варианты:
Первый вариант я уже использовал в паре проектов, правда не собственно sIFR, но не суть важно, результатом я остался не очень доволен. Сборки-пересборки Flash-файла со шрифтом, проверки на флеш, «рамочка» в IE7, не кошерно в конце концов. Второй вариант — всегда считал слишком тяжеловесным, как по трафику (файлы с отрендеренными шрифтами весят прилично, да ещё и не всегда корректно конвертируются), так и по нагрузке на процессор клиента. Так что в продакшен его ни разу не пустил.
Так я пришёл к третьему варианту. Однажды я уже прорабатывал этот способ на одном из тогда ещё php-проектов, вычитав идею на A List Apart. Работает и работает вполне сносно, хотя в этом методе по-прежнему использовался JavaScript. Более того, теперь мы разрабатываем проекты только на Django, так что я пошёл на поиски и через некоторое время нашёл два похожих проекта: django-cairo-text и django-image-replacement. Первый обладает достаточно широкими возможностями, но не умеет рисовать шрифтом из файла, только одним из установленных в систему, что в моём случае абсолютно не подходит, второй же слишком прост для моих нужд и использует не совсем удобные для меня подходы.
Но база есть, есть цель и я, как водится, решил написать свои костыли с турбо-приводом. Собственно то, что из этого получилось, я и хочу представить на ваше обозрение.
Для работы требуются установленные: PIL и Freetype2
Разместите файл headline.py в папку templatetags вашего приложения.
Для настройки доступны такие параметры:
В этом случае, в качестве параметров можно передавать как переменные и простые строки, заключенные в двойные кавычки, так и списки и словари. На выходе имеем список headers из объектов {file, text, width, height}:
Вот, что, к примеру, может получиться в финале. Я не дизайнер и шрифты подбирал «на глазок», так что за них прошу ногами не пинать.
Таким образом для клиента это выглядит как ручная нарезка, для сервера — нагрузка носит разовый характер, для разработчика всё просто и прозрачно. Профит!
Ещё раз ссылки по теме:
За сим спасибо, принимаю отзывы по теме, любой степени лестности.
Своими мыслями, поиском и конечным решением я и хотел бы поделиться с вами.
Преамбула
Итак, в принципе, какие у нас есть варианты:
- Заменять на Flash: sIFR, swftype;
- рисовать на canvas JavaScript`ом: cufon, typeface;
- использовать для этих целей сервер.
Первый вариант я уже использовал в паре проектов, правда не собственно sIFR, но не суть важно, результатом я остался не очень доволен. Сборки-пересборки Flash-файла со шрифтом, проверки на флеш, «рамочка» в IE7, не кошерно в конце концов. Второй вариант — всегда считал слишком тяжеловесным, как по трафику (файлы с отрендеренными шрифтами весят прилично, да ещё и не всегда корректно конвертируются), так и по нагрузке на процессор клиента. Так что в продакшен его ни разу не пустил.
Так я пришёл к третьему варианту. Однажды я уже прорабатывал этот способ на одном из тогда ещё php-проектов, вычитав идею на A List Apart. Работает и работает вполне сносно, хотя в этом методе по-прежнему использовался JavaScript. Более того, теперь мы разрабатываем проекты только на Django, так что я пошёл на поиски и через некоторое время нашёл два похожих проекта: django-cairo-text и django-image-replacement. Первый обладает достаточно широкими возможностями, но не умеет рисовать шрифтом из файла, только одним из установленных в систему, что в моём случае абсолютно не подходит, второй же слишком прост для моих нужд и использует не совсем удобные для меня подходы.
Но база есть, есть цель и я, как водится, решил написать свои костыли с турбо-приводом. Собственно то, что из этого получилось, я и хочу представить на ваше обозрение.
Итак django-headline
Что мы умеем на сегодня
- Рендеринг картинок из шаблона тремя путями: фильтром, тегом и тегом, меняющим контекст
- Естественно, кеширование ранее отрендеренных изображений
- Определение стандартных стилей шрифта через классы
- Автоматическая замена html-entities на юникодные символы
- Разбиение текстовой строки по br или по словам
- Собственные настройки расположения шрифтов и папки для кеша
- Опциональная оптимизация выходного png, через внешние утилиты
Установка и настройка
Для работы требуются установленные: PIL и Freetype2
Разместите файл headline.py в папку templatetags вашего приложения.
Для настройки доступны такие параметры:
# Папка для кеша картинок (относительно вашего MEDIA_ROOT/MEDIA_URL)
HEADLINE_CACHE_DIR = 'upload/textcache'
# Папка для шрифтов (относительно вашего MEDIA_ROOT)
HEADLINE_FONTS_DIR = 'fonts'
# Если это требуется, путь к оптимизатору
HEADLINE_PNG_OPTIMIZER = "optipng -o7 %(file)s"
# Пресеты настроек отображения
HEADLINE_CLASSES = {
"<class_name>": {
'font': <file>,
'size': <size>,
'color': <hex color>,
'decoration': ['underline', 'strikeout'], # Optional
},
...
}
Примеры использования
{% load headline %}
Как фильтр
{{ foo|headline:"font.ttf,20,#000" }}
{{ foo|headline:"font.ttf,20,#000,underline,all" }}
{{ foo|headline:"base,br" }}
Как тег
{% headline "font.ttf,20,#000" %}Big {{ foo }}{% endheadline %}
{% headline "font.ttf,20,#000,strikeout,none" %}Big {{ foo }}{% endheadline %}
{% headline "base" %}Big {{ foo }}{% endheadline %}
Как тег, модифицирующий контекст
{% headlines foo_list bar_dict baz_var "And some text" as headers "font.ttf,20,#000" %}
{% headlines foo_list bar_dict baz_var "And some text" as headers "font.ttf,20,#000,all" %}
{% headlines foo_list bar_dict baz_var "And some text" as headers "base" %}
В этом случае, в качестве параметров можно передавать как переменные и простые строки, заключенные в двойные кавычки, так и списки и словари. На выходе имеем список headers из объектов {file, text, width, height}:
{% for head in headers %}
<img src="{{ head.file }}" alt="{{ head.text }}" width="{{ head.width }}" height="{{ head.height }}" />
{% endfor %}
Вот, что, к примеру, может получиться в финале. Я не дизайнер и шрифты подбирал «на глазок», так что за них прошу ногами не пинать.
Таким образом для клиента это выглядит как ручная нарезка, для сервера — нагрузка носит разовый характер, для разработчика всё просто и прозрачно. Профит!
Ещё раз ссылки по теме:
За сим спасибо, принимаю отзывы по теме, любой степени лестности.