02 июля

Текст в кривых на fabricjs

Наверняка все, кто занимается html-версткой, сталкивались с векторными изображениями в формате svg.

Вообще SVG (Scalable Vector Graphic) - это язык для описания двумерной графики в XML. Он включает в себя три типа объектов: фигуры, изображения и текст. Как видно из названия, одним из главных преимуществ данного формата является возможность его масштабировать без потери качества, а следовательно для svg нет необходимости даже задумываться о retina-адаптации - векторные изображения будут четкими вне зависиморсти от плотности пикселей экрана.


Демо Скачать

Но сегодня я хотел бы поговорить немного не об этом.

Одним из типов объектов, поддерживаемых svg является текст, при этом если посмотреть код, он будет иметь следующий вид:

<text>Текст в SVG</text>

Чтобы указать шрифт, которым мы хотим напсать текст, используем знакомый синтаксис инлайновых стилей:

<text style="font-family:'MyriadPro-Regular'; font-size:12px;">Текст в SVG</text>

или

<text font-family="MyriadPro-Regular" font-size="12px">Текст в SVG</text>

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

При использовании svg изображения в web выход есть, также хорошо знакомый из css - можно подключить внешний файл шрифта через @font-face. Или же можно использовать описание шрифта и подключение внешнего файла через font-face-uri.

Однако, несмотря на подключение одного и тогоже файла, рендеринг шрифта может незначительно отличаться на различных устройствах.
Куда бОлшей проблемой, является невозможность использование подобных svg-изображений с текстом на стороне сервера или в большинстве векторных редакторов, вроде Adobe Illustrator - они заменят такой шрифт.

Я как-то уже писал об использовании fabric.js. С его помощью очень удобно строить всевозможные онлайн-редакторы и если в дальнейшем предполагается получившийся макет печатать, то использование текста очень осложняет задачу - стандартные шрифты у всех разные(Windows\Mac\Android\iOS), а отображение необходимо обеспечить строго одинаковое и чтобы была возможность работать с получившимся svg-макетом на сервере.

Решение может быть только одно - преобразовывать текст в кривые. Стоит заметить, что это стандартная процедура предпечатной подготовки - чтобы в типографии, вне зависимости от используемой ОС и установленных шрифтов, макет отображался как задумывал дизайнер.
Дабы не изобретать велосипед, я решил воспользоваться opentype.js и на его основе написать плагин для fabric.js.


Демо1 Демо2 Скачать

Новый тип элементов fabric.CurvesText построен на fabric.Textbox, но имеет кастомные обработчики построения текста используя opentype.js - каждый символ преобразуется в кривые и размещается на необходимом расстоянии от предыдущего, что обеспечивает одинаковое отображения вне зависимости от устройства, на котором интерпритируется данный текст, но что еще важнее - данный алгоритм задействован и для экспорта элементов в svg. Тоесть в svg файле мы уже увидим что-то вроде:

<path d="M26.68 23.21L24.01 23.21L24.01 30.55L22.95 30.55L22.95 23.21L20.29 23.21L20.29 22.27L26.68 22.27L26.68 23.21ZM30.12 28.13L27.39 28.13Q27.48 29.13 27.88 29.48Q28.29 29.83 29.23 29.83Q30.24 29.83 31.27 29.69L31.36 30.37Q30.60 30.69 29.10 30.69Q27.58 30.69 26.95 29.99Q26.31 29.29 26.31 27.61Q26.31 25.92 26.94 25.24Q27.56 24.56 28.99 24.56Q30.30 24.56 30.90 25.04Q31.50 25.51 31.51 26.47Q31.51 28.13 30.12 28.13M27.38 27.33L29.85 27.33Q30.50 27.33 30.48 26.47Q30.48 25.91 30.15 25.67Q29.83 25.43 29.04 25.43Q28.11 25.43 27.75 25.83Q27.39 26.24 27.38 27.33ZM35.74 27.49L35.74 27.53Q36.07 27.55 36.32 27.63Q36.57 27.72 36.79 27.92Q37.00 28.13 37.15 28.31Q37.29 28.49 37.48 28.90Q37.68 29.31 37.79 29.61Q37.90 29.91 38.14 30.55L37.08 30.55Q36.87 30.02 36.79 29.81Q36.70 29.60 36.54 29.23Q36.38 28.86 36.28 28.73Q36.19 28.59 36.03 28.38Q35.86 28.17 35.71 28.11Q35.56 28.04 35.36 27.98Q35.16 27.91 34.90 27.91L34.84 27.91L34.04 27.91Q34.09 28.29 34.09 28.47L34.09 30.55L33.07 30.55L33.07 24.71L34.09 24.71L34.09 26.45Q34.09 26.76 34.03 27.12L34.84 27.12Q35.26 27.12 35.56 26.97Q35.86 26.83 36.11 26.46Q36.36 26.10 36.51 25.75Q36.67 25.40 36.92 24.71L37.98 24.71Q37.83 25.10 37.77 25.26Q37.70 25.43 37.57 25.74Q37.45 26.05 37.38 26.18Q37.30 26.30 37.18 26.53Q37.06 26.76 36.97 26.85Q36.87 26.95 36.73 27.09Q36.58 27.23 36.45 27.29Q36.31 27.36 36.13 27.41Q35.95 27.47 35.74 27.49ZM43.84 29.71L43.94 30.39Q43.09 30.69 41.95 30.69Q40.42 30.69 39.80 30.00Q39.18 29.31 39.18 27.62Q39.18 25.94 39.81 25.25Q40.44 24.56 41.95 24.56Q43.10 24.56 43.83 24.84L43.70 25.50Q42.91 25.43 42.12 25.43Q41.07 25.43 40.66 25.89Q40.24 26.36 40.24 27.62Q40.24 28.89 40.65 29.36Q41.06 29.83 42.12 29.83Q43.09 29.83 43.84 29.71ZM49.98 25.55L47.86 25.55L47.86 30.55L46.84 30.55L46.84 25.55L44.72 25.55L44.72 24.71L49.98 24.71L49.98 25.55ZM57.49 27.53L57.49 27.56Q58.28 27.62 58.62 28.00Q58.95 28.38 58.95 29.11Q58.95 29.99 58.43 30.31Q57.91 30.63 56.61 30.63Q54.91 30.63 53.91 30.56L53.91 24.72Q54.79 24.65 56.29 24.65Q57.68 24.65 58.21 24.97Q58.75 25.29 58.75 26.21Q58.75 26.83 58.45 27.15Q58.15 27.48 57.49 27.53M54.87 27.18L56.41 27.18Q57.18 27.18 57.48 26.99Q57.78 26.81 57.78 26.29Q57.78 25.80 57.45 25.62Q57.12 25.45 56.25 25.45Q55.42 25.44 54.87 25.45L54.87 27.18M54.87 27.91L54.87 29.82Q55.05 29.82 55.59 29.82Q56.13 29.83 56.47 29.83Q57.30 29.83 57.61 29.64Q57.93 29.45 57.93 28.89Q57.93 28.34 57.60 28.13Q57.26 27.91 56.41 27.91L54.87 27.91ZM66.30 27.05L64.58 26.61Q63.70 26.40 63.33 25.84Q62.95 25.28 62.95 24.31Q62.95 23.59 63.10 23.15Q63.25 22.71 63.61 22.49Q63.98 22.27 64.43 22.20Q64.88 22.13 65.64 22.13Q67.10 22.15 68.10 22.37L68.02 23.13Q66.86 23.07 65.68 23.07Q65.16 23.07 64.90 23.10Q64.65 23.12 64.41 23.24Q64.17 23.36 64.09 23.62Q64.02 23.88 64.02 24.33Q64.02 24.99 64.25 25.27Q64.48 25.55 65.06 25.69L66.74 26.11Q67.66 26.34 68.04 26.89Q68.41 27.44 68.41 28.44Q68.41 29.81 67.79 30.25Q67.17 30.69 65.64 30.69Q64.33 30.69 63.07 30.47L63.14 29.69Q65.16 29.76 65.67 29.75Q66.66 29.75 67.00 29.49Q67.34 29.24 67.34 28.41Q67.34 27.73 67.11 27.46Q66.87 27.19 66.30 27.05ZM76.12 22.27L73.62 30.25Q73.51 30.55 73.21 30.55L72.14 30.55Q71.82 30.55 71.73 30.25L69.22 22.27L70.32 22.27L72.27 28.83Q72.44 29.43 72.51 29.73L72.84 29.73Q72.96 29.24 73.09 28.82L75.03 22.27L76.12 22.27ZM82.21 30.55L82.09 29.67Q81.03 30.71 79.62 30.71Q78.24 30.71 77.62 29.67Q77 28.64 77 26.39Q77 23.95 77.76 23.03Q78.51 22.11 80.46 22.11Q81.76 22.11 82.76 22.37L82.65 23.16Q81.64 23.06 80.52 23.06Q79.57 23.06 79.08 23.31Q78.60 23.55 78.36 24.29Q78.12 25.02 78.12 26.46Q78.12 28.29 78.51 29.04Q78.91 29.78 79.90 29.78Q80.84 29.78 81.94 28.98L81.94 25.76L82.98 25.76L82.98 30.55L82.21 30.55Z" fill="#000000"/>

Помимо предпечатной подготовки, плагин может быть полезен и при разработки сервисов взаимодействия онлайн\оффлайн редакторов, например - fonts.jpgx.ru - сервис позволяет использовать шрифт без установки на свой компьютер. Также он имеет интеграцию с GoogleFonts. Просто напишите необходимый вам текст, подберите шрифт и выгрузите его в виде кривых для дальнейшего использования в вашем макете.


fonts.jpgx.ru