Raphaël

Предисловие: мне поднакопилось что сказать, так что если я не успею высказать все мысли за одну статью, а так скорее всего и будет, то разбор примера по косточкам будет в следующей статье. Я использовал достаточно много сторонних библиотек для построения примера, думаю что все обсуждать не буду но обо всех скажу хоть слово.

Дело началось не так давно, когда заказчик высказал идею что на сайте должен быть виджет позволяющий рисовать по верх картинки линии как в MS Paint. Более того линии которые ты нарисовал, нужно выделить, и в табличке рядом заполнить дополнительные параметры. У меня перед глазами пронеслись все прожитые годы библиотеки векторной и растровой графики для javascript. Сначала я думал что я буду использовать что-то на основе canvas, хорошо хоть опыт уже есть, но потом понял что в голове крепко засела мысль о Raphaël. Ну и хорошо, я давно хотел с ней (библиотекой) поработать, но не было реального примера.

В двух словах Raphaël — это библиотека которая умеет рисовать векторную графику в формате SVG во всех нормальных браузерах, в остальных она умеет рисовать в формате VML. Как она умеет это делать меня интересует мало, главное что она предоставляет более менее удобное и совершенно недокументированное API. Почему я говорю недокументированное?! Потому что глядя на официальный мануал я чуть не заплакал, там нихуя нет ничего нельзя понять. Ну я решил раз в мануале нет, пох, я тут код jQuery читаю нормально, что мне какой-то Raphaël, но был сильно не прав потому как в коде творится полный пиздец кромешный ужас летящий на крыльях ночи.

Нет, я прекрасно понимаю когда кто-то считает координаты кривой Безье второго порядка он должен писать нечто вроде


Math.sqrt(Math.abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x)))

Тут даже можно догадаться что rx2 это произведение R (радиуса) на X (координаты по иксу) в квадрате

Я могу понять регулярное выражение которое проверяет валидность записи цвета в трех форматах (hex, rgb, hsb и hsl можно считать как один)


/^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgb\(\s*([\d\.]+\s*,\s*[\d\.]+\s*,\s*[\d\.]+)\s*\)|rgb\(\s*([\d\.]+%\s*,\s*[\d\.]+%\s*,\s*[\d\.]+%)\s*\)|hs[bl]\(\s*([\d\.]+\s*,\s*[\d\.]+\s*,\s*[\d\.]+)\s*\)|hs[bl]\(\s*([\d\.]+%\s*,\s*[\d\.]+%\s*,\s*[\d\.]+%)\s*\))\s*$/i

Но, блядь, я не понимаю каким надо быть мудОфилом, что бы писать вот так:


path = ["C"][concat](a2c[apply](0, [d.x, d.y][concat](path.slice(1))))
now = [+from[attr][0] + pos * ms * diff[attr][0], +from[attr][1] + pos * ms * diff[attr][1], (2 in to[attr] ? to[attr][2] : E), (3 in to[attr] ? to[attr][3] : E)][join](S)

Я для особо «тупых» переведу: вот эти [concat] и [apply] это всего лишь вызов соответствующих методов, но почему же, блядь, не [slice] ?


["C"].concat(a2c.apply(0, [d.x, d.y].concat(path.slice(1))))

а вот эти «2 in to[attr]» это ничто иное как


if(to[attr] && to[attr][2])
	return to[attr][2]
else 
	return E // E = 2.71

Тут возникает вопрос почему так сложно, потому что если to[attr] == null, то to[attr][2] вызовет ошибку и прервет исполнение функции. С таким подходом код становиться нечитабельным и плохо сопровождаемым, но я понимаю что Дмитрия Барановского все устраивает, поэтому он пишет еще такое:


~~double

Оператор ~~ приводит double или строку вида «3.14» к integer, то есть к целому, то есть к 3.


javascript:(function(){alert(~~(""+Math.PI))})()

Ну и последние — это сокращенные записи if-else, но не такие ?: а такие &&|| , хотя насмотревшись на его код я и сам пару раз такое использовал


if(c) b = c else b = d;
b = c ? c : d;
b = c && c || d;

На чём я закончил, перед тем как отвлечься на порыв ненависти к разработчику Raphaël?! Ах да я рассказывал какая это классная библиотека как искал описание API. После бесполезного чтения мануала и безрезультатного просмотра исходников я открыл примеры и начал заниматься реверс инженерингом, та еще радость, но это единственное что помогло. Потом еще в гугле нашелся удачный пример который дал мне толчок для написания своего плагина.

Дальше больше…

16 Комментарии “Raphaël

  1. Ну вот, пиарил-пиарил на пыхе, а теперь говоришь что фуфло :)
    Кстати в пайтоне я юзаю такую конструкцию: b = c if c else d

  2. @adw0rd
    Я ни слова о Raphaël на форуме не написал, и тут я не говорю что он фуфло, я даже сказал что тут более-мение удобный API. Другое дело что далеко не все смотрят в код пока он работает, а я вот полез…

    Да и когда я соберусь выучит питон я обязательно буду обращатся к тебе по каждому хелоу-ворд c идиотскими нубскими вопросами :)

  3. ну так там реально крутые примеры, только пример с буковками (хельветика) глючит

    а вот самому такую шнягу сделать нельзя поому что API не описан нормально.

  4. Гы… я боюсь показывать тебе свой код на Java (основном для меня языке)… хотя, вот адын экземпляр http://govnokod.ru/2101 — и это еще цветочки :)

  5. @ShadowX
    ничего страшного нет в умении писать в одну строку, всегда сам пытаюсь так сделать

    вот смотри, это ведь не гавнокод

    
    DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(new File("path/to/file"))));
    
  6. Обратите внимание на оперу.
    В 10й версии(но не в 9.64), а так же еще хз в каких версих есть очень неприятный баг, побороть который я так и не смог: анимациия svg узлов не работает. Точнее работает, но не перерисовывается. Точнее перерисовывается но не всегда. Зависит от расположения звезд на небе, а так же от положения тега svg на экране(:D). Если он в верхней части, то иногда частично не перерисовываются изменения. Если в нижней, то все нормально.

  7. @morr
    Я даже незнаю как попросить код (тесткейс, степ ту репродьюс) который показывает этот баг

  8. парсер сожрал тег.
    (добавил много [br] сверху и снизу)

  9. @morr
    у тебя там проблема в CSS убери position: relative и absolute из примера и все будет работать, я еще float:left удалял

Комментарии закрыты