Pull to refresh

Инструмент для рисования снежинок в браузере

Vector graphics *
Снежинка своими руками. Хабрахабр
Тема оформления «Хабрахабр».

Ещё 2 дня назад я закончил разработку инструмента для рисования снежинок, отладил его в тепличных локальных условиях и готов был отправить в дальнее плавание. Но запуск «проекта» в открытый интернет пришлось 2 раза откладывать. Сначала при интеграции со сторонним сайтом отказались работать кроссдоменные AJAX-запросы методом POST (а GET'а мне не для всех запросов было достаточно), потом на медленном канале проявила себя в виде глюков асинхронная загрузка данных и представления. Сейчас всё вроде бы пофикшено, выложено и ожидает по отношению к себе проявлений внимания.

Буду говорить о разработке, планах, нагло пиариться предлагать сотрудничество. Сейчас пойдёт много текста, а внизу ещё одна картинка.

Предыстория, переходящая в историю


Страсть к снежинкам у меня возникла как-то неожиданно. Разрабатывал библиотеку экспорта документов в PDF и когда дошёл до преобразования векторных объектов подумал, что неплохо было бы по завершению разработки набросать какую-то клёвую демку и сделать этим самым себе рекламу. Запускаться хотел до Нового года, поэтому и темы рассматривал соответствующие.

Загорелся разработать генератор снежинок по заданным метеоусловиям, перечитал много информации по этому поводу и даже немного продвинулся в отрисовке снежных кристаллов по заданным параметрам (см. первые скриншоты). Но потом понял, что полноценный генератор правильных снежинок я не успею сделать и решил ограничиться редактором. К тому же, это и веселее для пользователя, поскольку предполагает его личное участие. Так родилась идея разработки интерактивной открытки. Впоследствии — отдельной открытки, а не как части какого-то другого проекта. К слову, проект, связанный с PDF, я так и не успел запустить до праздников.

На ранних стадиях разработки инструмент рисования снежинок представлял из себя SVG-изображение со встроенной JavaScript-библиотекой. Работало, разумеется, не во всех браузерах, поэтому в один прекрасный момент я пересел на широко известный в наших узких кругах графический фреймворк Raphaël. Для ещё большего скрашивания будней веб-разработчика был подключен jQuery. jQuery стал отвечать за AJAX-запросы к серверу, на котором хранятся данные и за хитрые платформонезависимые манипуляции с DOM. На Raphaël была возложена независящая от браузера отрисовка всего векторного и взаимодействие объектов на холсте с мышью пользователя.

Raphaël пришлось совсем немного допилить, поскольку были проблемы с обновлением холста в Хроме (там есть специальный костыль для WebKit, но он срабатывает не для всех версий браузеров на WebKit) и не хотели менять своё положение в стопке графических объектов элементы, заключённые в тег <a> (а это не только те, которые в ссылке, но и те, которым задана всплывающая подсказка). Первое полечилось корректировкой регулярного выражения, определяющего движок браузера. Второе — добавлением автоматического удаления <a> при сбросе до пустых строк параметров href и title. По-хорошему, надо было бы допилить сами методы перемещения объектов, но там бы я не отделался малой кровью.

Кстати, тег <a> в SVG мешал и корректной инициализации «закладочной кнопки» AddThis. Его я использовал для того, чтоб не городить велосипед с расшариванием результатов рисования.

Теперь по поводу кроссдоменных AJAX-запросов методом POST. К сожалению, они не поддерживаются браузерами в целях обеспечения безопасности пользователя. Метод GET таких ограничений не имеет, но имеет де-факто ограничение по длине. Де-юре так быть не должно, однако некоторые бразузеры, не будем тыкать пальцами, не позволяют делать запросы по ссылкам длиной чуть более 2 тыс. знаков. Да и как-то некрасиво гонять в адресах большие объёмы данных. Поэтому было решено в пределах своего домена продолжать передавать POST, а при размещении приложения на стороннем сайте, резать данные на куски, передавать их методом GET (по технологии JSONP) и только при передаче последнего куска выполнять запрос на сервере.

Для того, чтоб было удобно использовать приложение на любом сайте, весь код вынесен в JS библиотеку. Подключается и инициализируется она вставкой на страницу всего нескольких тегов. Поэтому даже индексная страница на сайте проекта представляет из себя простой HTML-файл. Ссылка на библиотеку в теге <script> может в якоре (всё, что после #) содержать дополнительные параметры: идентификатор клиента (используется только при размещении кода на стороннем сайте), тему оформления и идентификатор снежинки по умолчанию.

Через якорь передаются и идентификаторы в ссылке на конкретную снежинку с конкретной темой оформления. То есть, если убрать со страницы приложение, ссылка останется рабочей, просто без открытки. Это первая важная причина, по которой использовались якоря, а вторая — они позволяют по максимуму отказаться от скриптов на сервере.

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

В общем, темы могут очень сильно отличаться друг от друга и изначально я планировал использовать эту возможность для брендирования открыток. Жаль, что не успел закончить раньше. Но впереди ещё Рождество, Старый новый год, Новый год следующего года… Так что обращайтесь, можем куда-нибудь интегрировать открыточку.

Снежинка своими руками. Белый кролик
«Белый кролик» — основная тема грядущего года.

Планы

  • Добавить режим печати сложенной снежинки для вырезания её из бумаги. Как в детстве, но технологичнее.
  • Добавить экспорт в векторные и растровые форматы.
  • Доработать выбор языка и смену темы прямо в приложении, а не через ссылку.
  • Добавить персональные страницы со списком собственных снежинок и статистикой (данные уже собираются, но пока лишь привязываются к идентификатору пользователя, который бережно хранится в COOKIE).
  • Добавить рейтинг снежинок.
  • Добавить возможность оставлять комментарии, личные поздравления и фотографии.
  • Доработать рисование сдвоенной 12-угольной снежинки.
  • Доработать перемещение и зуммирование при редактировании.
  • Оптимизировать код.


UPD1: Сейчас при использовании приложения

UPD2: Вчера при использовании приложения на стороннем сайте без регистрации в качестве партнёра посетителям отдавались ссылки на изображения на моём сайте. Устранил это недоразумение. И ещё. Если кто-то планирует размещать код у себя или просто желает получать новости о проекте, напишите мне на yuriyapostol@gmail.com что-нибудь вроде «хочу получать новости о проекте Снежинка» или «хочу быть в курсе об изменениях в API Снежинок».

UPD3: Код для вставки приложения на свой сайт:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<script src="http://apostolstudio.com/lab/snowflake/raphael-apos.min.js" type="text/javascript" charset="utf-8"></script>
<script src="http://apostolstudio.com/lab/snowflake/snowflake.js" type="text/javascript" charset="utf-8"></script>

<div id="snowflake_container"><div id="snowflake_paper">Загрузка...</div></div>


Все скрипты можно перенести в <head>. Для инициализации приложения с особыми параметрами перечислите их в ссылке к основному скрипту после #. Пример с указанием темы и снежинки по умолчанию:

<script src="http://apostolstudio.com/lab/snowflake/snowflake.js#theme=Rabbit&flake=kOQxOPNwnQZS" type="text/javascript" charset="utf-8"></script>
Tags: снежинкаснеготкрыткаsvgraphaelajax
Hubs: Vector graphics
Total votes 63: ↑55 and ↓8 +47
Comments 19
Comments Comments 19

Popular right now