Архив за Март 2009

  • Фотошоп для веб-разработчика. Кнопочки

    В этой статье я полностью продемонстрирую процесс создания красивых кнопочек — от получения макета до готового решения.

    button-example

    Дизайнер хочет, чтобы на сайте было 10 разных цветов таких кнопок, причем при наведении курсора цвет должен немного бледнеть. Вариант «в лоб» — нарезать кучу картинок под каждый цвет — нам, как правильным разработчикам, не подходит, поэтому мы создадим специальную маску, под которую будем класть разные градиенты. В итоге можно будет обойтись всего двумя небольшими картинками. А если постараться — то и одной.

    Открываем макет и анализируем изображение. Кнопка представляет из себя обычный векторный шэйп, у которого заданы эффекты:

    ss11

    Первое, что бросается в глаза, это размытая верхняя и левая границы кнопки. Дизайнер не очень-то старался, и нам нужно это исправить.

    Давайте рассмотрим подробнее слой shape. Это специальный векторный слой, состоящий из двух частей: цвет и маска.

    ss3

    Дважды кликнув на первый квадратик мы можем поменять цвет шэйпа, кликнув на второй — отредактировать его внешний вид.

    Кликаем на маску и выбираем Direct Selection Tool:

    ss2

    Выделяем все верхние узлы:

    ss4

    Теперь с помощью стрелок вверх/вниз на клавиатуре перемещаем узлы в нужное положение, чтобы верхняя граница стала четкой. Помните, что шаг смещения зависит от текущего масштаба. Я рекомендую увеличить масштаб до 500%. Вы можете временно включать/отключать отображение векторной рамки с помощью Ctrl+H/⌘+H, это поможет вам точнее разместить узлы.

    Проделайте такую же операцию с левыми узлами. В итоге должна получиться вот такая картинка:

    ss5

    Косяк дизайнера мы исправили, теперь переходим к самой интересной части — реконструкция изображения. Нам нужно сделать так, чтобы вместо зеленого градиента была дырка, под нее мы сможем подкладывать любой другой градиент или картинку. 

    Разбираем шэйп на составляющие. У нас есть градиент (тело кнопки), обводка и тень, все это указано с помощью фильтров слоя. Для дальнейшей работы нам нужно сделать дубликат слоя shape, чтобы перед глазами всегда был оригинал, на который будем ориентироваться.

    Делаем правый клик на иконке fx у дубликата и в меню выбираем Create Layers. Мы превратили все эффекты в полноценные слои, с которыми можно работать. 

    Сразу же обращаем внимание на то, что обводка стала чуть темнее:

    ss7

    Это объясняется особенностями работы фильтров в фотошопе (вам еще должны были показать сообщение о том, что можете получить не то, чего ожидали). Для того, чтобы добиться правильных цветов, дизайнеру пришлось в качестве цвета обводки указать градиент от светло-зеленого до темно-зеленого.  Нас это не устраивает, потому что зеленый градиент будет странно смотреться на красной кнопке 🙂

    Исправим эту проблему. Выделяем слой с обводкой (у меня он называется shape copy’s Inner Stroke) и обесцвечиваем его: Image → Adjustments → Desaturate. Обводка стала черно-белой — как раз то, что нам нужно — но все равно слишком темной. Снизим прозрачность у обводки: выставим параметр Opacity в 60%. Теперь дубликат практически не отличить от оригинала (учитывайте, что на скриншоте масштаб 400%):

    ss8

    Тень (shape copy’s Drop Shadow) тоже имеет зеленоватый оттенок, обесцветим и ее с помощью команды Desaturate.

    Осталось вырезать внутренности кнопки, чтобы тень была поверх белого фона, а обводка — поверх прозрачного. Сейчас все слои эффектов, кроме Drop Shadow, находятся в режиме маски отсечения (clipping mask): слои накладываются поверх пикселей основного слоя. Нам нужно перевести их в нормальный режим, для этого делаем Alt-click на линии между слоями shape copy и shape copy’s Gradient Fill. Получим вот такой результат:

    ss9

    Отключаем слои с Color Fill и Gradient Fill — они нам больше не нужны. Теперь нам нужно наложить на оставшиеся слои маски. Делаем Ctrl-click/⌘-click по маске слоя shape copy, выделяем слой Layer 1 и нажимаем на иконку mask-icon в палитре слоев. Проделываем такую же операцию для слоев shape copy’s Inner Stroke и shape copy’s Drop Shadow. Получим вот такой результат:

    ss10

    Конечно же, это не то, что мы хотели получить: прозрачной должна быть внутренняя часть кнопки, а не внешняя. Чтобы исправить это, нужно инвертировать маску в слоях shape copy’s Drop Shadow и Layer 1. Выделяем маску каждого слоя и выполняем Ctrl+I/⌘+I, отключаем слой shape copy. Получилось то, что нам нужно:

    ss111

    Теперь необходимо обрезать ненужные белые пиксели. Не торопитесь выбирать инструмент Crop и прицельно выделять блок — есть более простой и красивый способ. Выбираем Image → Trim, в окне выбираем Based On: Top Left Pixel Color .

    Осталось подготовить картинку для использования на странице. Для создания кнопки хорошо подойдет способ «звездочка», нужно только правильно спозиционировать уголки. Объединяем все слои (Layer → Merge Visible) и вызываем Filter → Other → Offset. В диалоговом окне указываем смещение по горизонтали и вертикали в 9 пикселей, в качестве значения Undefined Areas выбираем Wrap Around:

    ss12

    Так как правильные мальчики и девочки верстают сайты с учетом изменения размера шрифта, нужно добавить нашей картинке запас прочности. Для этого увеличиваем размер холста до 300×80 пикселей и растягиваем последний горизонтальный и вертикальный пиксели (тут очень удобно воспользоваться инструментами Single Row Marquee Tool и Single Column Marquee Tool).

    Все, работу над изображением мы закончили. Сохраняем картинку в формате PNG-24 под названием, например, button-mask.png.

    Теперь переходим к разметке. Тут все довольно просто: создаем контейнер, в котором размещается 4 уголка. Для того, чтобы надпись была по середине кнопки, мы не будем использовать CSS-свойство height, вместо него воспользуемся свойством line-height.

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    	<head>
    		<title>Styled button example</title>
    		<style type="text/css">
    			.styled-button {
    				text-align:center;
    				position:relative;
    				width:6em;
    
    				/* Вместо высоты */
    				line-height:2.3em;
    				color:#428135;
    				background:url(green-gradient.png) #8fbd81 repeat-x;
    				overflow:hidden;
    			}
    
    			.styled-button .cn {
    				display:block;
    				background:url(button-mask.png) repeat-x;
    				width:100%;
    				height:80px;
    				position:absolute;
    
    				/* Радиус скругления */
    				left:-9px;
    				top:-9px;
    			}
    
    			.styled-button .cn.tr,
    			.styled-button .cn.br {
    				/* Эмуляция свойства right для IE6 */
    				margin-left:100%;
    			}
    
    			.styled-button .cn.bl,
    			.styled-button .cn.br {
    				/* Такое же значение, как у line-height */
    				margin-top:2.3em;
    			}
    		</style>
    	</head>
    	<body>
    		<div class="styled-button">
    			Кнопка
    			<span class="cn tl"></span>
    			<span class="cn tr"></span>
    			<span class="cn bl"></span>
    			<span class="cn br"></span>
    		</div>
    	</body>
    </html>
    

    Осталось только для IE6 прописать фильтр, чтобы отображался полупрозрачный PNG.

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

    На что нужно обратить внимание в этом уроке:

    • Базовое сведения о работе векторных и растровых масок.
    • Некоторые не очевидные способы решения стандартных задач, типа Image → Trim или Single Row Marquee Tool.
    • Работа с эффектами слоев.
    • Фильтры нужны не только дизайнерам.

    Если сама идея описания фотошопа для веб-разработчиков нравится — буду писать дальше.

  • Фотошоп для веб-разработчика. Вступление

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

    Считается, что фотошоп слишком «тяжел» для повседневных копи-пэйст нужд веб-разработчика, поэтому им предлагают всякого рода альтернативы: Adobe Fireworks, Paint.NET, Pixelmator и так далее. А также жуткий пиздец под названием Gimp (я считаю, что суровые линуксоиды должны править картинки в командной строке). Я сам давно пытался найти альтернативу фотошопу, но все поиски оказались безуспешны: как ни странно, мне не хватало функциональности.

    Я очень люблю графику, а еще больше люблю ее оптимизировать. Я сейчас не говорю о той «оптимизации», где нужно просто подергать слайдеры или запустить программку, я говорю о настоящей оптимизации, когда необходимо реконструировать  изображение, чтобы оно меньше весило и выглядело лучше. Я слишком ленив, чтобы создавать сотню похожих картинок разного цвета, я лучше сделаю одну сложную маску и буду менять цвет через CSS. Для достижения этих целей я пользуюсь теми же инструментами, что и дизайнеры. Разница в том, что дизайнер оперирует эмоциями, а я — цифрами. Дизайнер делает так, чтобы картинка нравилась пользователю, а я делаю так, чтобы она лучше сжималась и с ней было удобнее работать в CSS. Дизайнер не знает, как лучше нарисовать тень, чтобы она как можно меньше весила в PNG, а я не знаю, как эту тень сделать похожей на настоящую. Мы дополняем друг друга, при этом каждый делает свою работу и не вмешивается в чужую. 

    Можно, конечно, полчаса стоять над душой у дизайнера и объяснять ему на пальцах, что нужно сделать с картинкой, но я лучше потрачу 5 минут и сделаю все сам. Если вы разделяете мою точку зрения, значит, мое время будет потрачено не зря.

  • Решение для float-блоков разной высоты

    Наткнулся на занимательную статейку в блоге Мозиллы про то, как решить извечную проблему с float-блоками разной высоты.

    Метки:
  • Аякс ради аякса

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

    Может, это я старею? Может, действительно за этим будущее и пора бы уже менять принципы создания сайтов? Вооружившись последним файрфоксом и файербагом решил проверить «под микроскопом» приведенные примеры. Действительно ли это наше будущее, или всего лишь очередной оральный вау-импульс для начинающих гиков?

    Основная проблема таких сайтов — сохранение истории навигации по сайту. Посмотрим, как это работает с точки зрения пользователя.

    1. Сайты, где используется раздражающая уже на пятом разе анимация, удалось завалить довольно быстро: достаточно быстро перейти по истории на 2—3 шага вперед/назад. В половине случаев я видел только крутящийся прелоудер, во второй половине случаев слетала история навигации. То есть я переходил куда угодно, но не туда, куда ожидал.
    2. Когда я хожу по истории обычных, олдскульных сайтов, браузер запоминает, где я закончил просматривать страницу. Угадайте с трех раз, какую часть страницы я видел на анимированных сайтах?
    3. Следующий пример поведения. Когда я захожу на сайты я обычно открываю интересующие меня страницы в новых табах с помощью Command-click. Естественно, некоторые разработчики плевать хотели на разные модели поведения пользователя, поэтому на одном сайте страницы загружались в том же окне при любом клике на ссылку.
    4. Даже не удивился, что кое-где перемещение по истории сопровождалось новым обращением на сервер. Такая вот экономия на траффике.

    Это те проблемы, которые я увидел как обычный пользователь. Теперь посмотрим, что я получу от такого подхода как разработчик. Иду на форум. Как и ожидалось, разработчики поимели целый букет проблем, которых раньше просто не было: начиная от неправильной инициализации скриптов при загрузке, заканчивая отслеживанием страниц с помощью Google Analytics.

    ***

    Всегда удивлялся тому, как разработчики любят усложнять себе жизнь. Проблемы не существует, но ее обязательно придумывают, не спят ночами чтобы решить ее, а потом радуются как дети работающему через жопу решению. К сожалению, программисты разучились думать как обычные люди — те самые, которые ежедневно ходят на сайты и ради которых эти сайты делаются. У таких разработчиков одна цель — показать, что они умеют пользоваться готовыми библиотеками.

    Но что больше всего меня позабавило: Яндекс-карты почему-то не подключаются на страницу, на них просто стоит ссылка. Вот такой вот аякс.

  • Краткий экскурс в профайлинг JS

    Недавно с коллегой переписывался о том, как нужно делать профайлиг JavaScript-кода. Решил, может информация будет еще кому-нибудь полезна. Предыстория: коллега делает анимацию на JS, пытаемся понять, почему она сильно тормозит.

    Внёс изменения. Поставил таймер на mouseOver. Получается, что функция calculateSize выполняется 20-23ms. До этого примерно так и было.

    Нужно не таймером, а профайлером замерять (есть в Firebug и последних версиях Webkit).

    Ну я имею в виду функцию FireBug’а console.time() и console.timeEnd(). Они делают то же, что профайлер, только для определенного куска кода.

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

    Я просто не могу понять в этом профайлере где именно тормозит. Там всё исписано в init() 🙂

    Вот смотри, сейчас профайлер тебе говорит, что во время работы твоего эффекта больше всего ресурсов жрет функция init() из jQuery, которая вызывается почти 6000 раз:

    firebug1

    Так как сама по себе эта информация нам мало полезна, тебе нужно найти ту функцию, которая так часто вызывает init(). Для этого отсортируем данные по колонке Time (общее время выполнения функции). Видим, что на первом и втором месте стоит jQuery-функция, а на 3 и 4 — функции calculateSize() и imgSize(), время выполнения которых — 588 и 547 мс соответcтвенно.

    firebug2

    Тут явно видно, что сами эти функции выполняются очень быстро (см. Own Time), но вот они вызывают другие функции, которые и дают те самые 588 и 547 мс.

    Смотрим calculateSize(), проблемные места:

    var prevImg = slctdImg.parent().prevAll();
    var nextImg = slctdImg.parent().nextAll();
    

    Это все выборки по дереву, очень тяжелые операции.

    Смотрим imgSize(), проблемные места:

    imgCont.width(newWidth).height(newHeight);
    imgCont.css({
    	width: newWidth,
    	height: newHeight,
    	margin: (!dir) ? "0 0 " + k + "px 0" : k + "px 0 0 0",
    	zIndex: count - num,
    	opacity: 1 - (num) / 30
    });
    

    два раза устанавливаешь width и height

    В целом, чтобы избавиться от этих проблемных мест, нужно полностью переписать логику работы библиотеки. Другой вопрос, даст ли это необходимый прирост производительности. Попробуй временно отключить изменение размеров картинки и opacity, просто сделай перемещение и посмотри, как работает. Если работает медленно, то проблема описана выше. Если работает быстро, значит, проблема в изменении габаритов и opacity, тут уже вряд ли что-то поделаешь.

    Метки: , , ,

← cтарое новое →