В этой статье мы познакомимся с Framer — инструментом прототипирования и дизайна, основанного на коде. Мы рассмотрим основные концепции, которые делают Framer эффективным интрументом прототипирования для дизайнеров и разработчиков. И мы собираемся воспроизвести один из переходов, найденных в приложении Design + Code.

Прежде чем начать, скачайте файлы проекта, чтобы следовать этому руководству. Вы должны открыть файл «DesignCode-Chapter-New.framer», чтобы начать работу, но, если вы почувствуете необходимость увидеть решение, вы можете скачать его здесь.

Интерфейс Framer

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

Вкладка «Дизайн»

Вкладка «Дизайн» может быть разбита на четыре основные части.

Framer Вкладка «Дизайн»

1.Боковая панель

Здесь у нас есть инструменты для создания артбордов, прямоугольников, овалов, текста, масштабирования рабочей области и внизу встроенная панель иконок.

2. Панель слоев

Как и большинство других инструментов проектирования, Framer также имеет панель слоев. Однако есть некоторые ключевые отличия. Мы рассмотрим их более подробно позже, чтобы вы могли понять, как работают слои во Framer.

3. Рабочая область

Вы можете использовать рабочую область для создания артбордов для самых разных телефонов, планшетов, часов, рабочих столов и даже телевизоров.

4. Панель свойств

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

Вкладка Код

Вкладка «Код» может быть разделена на пять частей.

Framer Вкладка Код

1. Боковая панель

Боковая панель очень похожа на панель в режиме дизайна, у вас есть разные инструменты для быстрой анимации ваших слоев, а также вы можете импортировать свои проекты из других приложений, нажав кнопку импорта. Вы также можете быстро получить доступ к документации по Framer или проверить свой код.

2. Панель слоев

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

3. Редактора кода

Очень легко начать кодить с помощью Framer. Он имеет очень привлекательную и полезную подсветку синтаксиса, нижняя часть области редактора зарезервирована для отображения ошибок, которые есть в вашем коде. И нам очень нравится функция Smart Autocomplete.

4. Окно предварительного просмотра

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

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

5. Панель свойств

Вы можете получить к ней доступ, щелкнув на значок редактирования. На этой панели вы увидите различные свойства вашей анимации, состояния или события.

Framer имеет хорошую функцию, она называется Auto-code. Если вы измените слой из окна предварительного просмотра, вы увидите изменения еще в двух местах: на панели свойств и в области редактора кода. Auto-code постоянно сохраняет код с вашими визуальными изменениями.

Основы дизайна

Основные сведения о Framer.

Слои

Слои во Framer очень похожи на слои в любом другом инструменте проектирования, но есть несколько небольших различий, которые отличают его. Мы все привыкли к концепции группировки в Sketch, где вы выбираете два или более слоев и создаете с ними группу. Технически, во Framer нет групп. Вместо этого слои «вложены», как div в веб-странице. Взгляните на артборд под названием «Page1». Он имеет несколько дочерних слоев. iOSGuide находится в верхней части этого дерева и сам содержит несколько дочерних слоев. iOSGuideImage содержит заголовок и основной текст. Эти текстовые слои «вложены», и, хотя они отображаются на панели слоев ниже iOSGuideImage, они фактически сидят над изображением и все еще видны на холсте. Давайте посмотрим короткий видеоролик о том, как это работает.

Выделение

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

Адаптивный макет

Одна из мощных функций Framers — это адаптивность по умолчанию. В зависимости от того, где и как вы размещаете слои на артбордах, Framer всегда будет пытаться определить, как вы хотите, чтобы он реагировал на изменения размера экрана. Так, например, если вы поместите слой, привязанный к правой стороне экрана, при изменении размера экрана, слой останется привязанным к этой позиции.

Предварительный просмотр ресайза

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

Основы кода

Основные понятия прототипирования во Framer можно разбить на четыре части. Они просты, и их освоение приведет вас на следующий уровень прототипирования.

1. Слои

Слои во Framer не похожи на слои, которые вы найдете в Sketch. Когда вы создаете слой, вы можете его стилизировать и добавлять изображения, тексты и видео. Слои могут быть разделены на другие слои и быть анимированы. Они являются строительными блоками Framer.

2. Анимация

Анимация — это то, что оживляет ваши слои. Вы можете анимировать свойства слоя, такие как цвет фона, высота, ширина, размер, непрозрачность, радиус рамки и т. д…

3. Состояния

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

4. События

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

Реализация

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

Большая часть первой части нашего кода будет сосредоточена на настройке различных элементов на артборде, но в частях Переход 1 (Открытие события) и Переход 2 (Закрытие события) мы будем работать над сворачиванием и разворачиванием анимаций соответственно.

Настройка

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

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

И, наконец, мы зададим состояния по умолчанию для кнопок «Play» и «Close».

Мы вынесем за пределы холста кнопку «Close», затем мы уменьшим кнопку «Play» до .5 и зададим непрозрачность 0.

# Setup

defaultSpring = "spring(280, 27, 5)"

textExample = "Three years ago, Apple completely revamped their design language for modern users. It is now much simpler, allowing designers to focus on animation and function rather than intricate visual details."

closeBtn.y = -40
playBtn.scale = .5
playBtn.opacity = 0

Мы выделим весь этот код, щелкнем правой кнопкой мыши и выберем «Fold». Вот, где функция Framer «Code Fold» действительно проявляет себя. Это создаст новый раздел для этого кода.

Хорошо держать это в стороне от нашего основного кода, чтобы он был чистым.

Framer code

Компонент страницы (Page Component)

Чтобы добавить пейджинг в наши карточки, нам нужно использовать PageComponent

Мы сделаем его дочерним слоем PageView, который является слоем из артборда Chapters. Затем устанавливаем положение Y. Поскольку у PageComponent теперь есть PageView, как родительский слой, любые значения позиции, которые он задает, относятся к его родительскому объекту. Когда мы устанавливаем Y-позицию на 60, то, на самом деле мы делаем отступ 60px вниз от верхней части слоя PageView. Чтобы компенсировать это позиционирование, мы установили высоту PageComponent с простым вычислением. Это быстрый способ установить значение свойства слоя, если вы не хотите устанавливать его вручную. Поскольку этот PageComponent должен прокручиваться только по горизонтали, мы установили scrollVertical в значение «false». Наконец, установка contentInset дает нашим страницам некоторый запас слева и справа. Не стесняйтесь играть с некоторыми из этих значений, чтобы увидеть, как они меняют макет.

pageComp = new PageComponent
parent: PageView
y: 60
height: PageView.height - 60
width: PageView.width
scrollVertical: false
contentInset:
left: 10
right: 10

Теперь у вас настроен PageComponent, но ему нужен контент. Добавление контента чрезвычайно просто. Нам просто нужно добавить страницы в наш PageComponent.

pageComp.addPage(Page1)
pageComp.addPage(Page2)

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

Настройки состояний

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

playBtn.states.Show =
opacity: 1
scale: 1
animationOptions:
curve: defaultSpring

playBtn.states.Hide =
opacity: 0
scale: .5
animationOptions:
time: .2

Здесь у нас есть два состояния «Show» и «Hide». Думайте о состояниях, как способе хранения свойств, между которыми мы можем переключаться. Мы также добавили опции анимации, чтобы получить хороший переход между этими двумя состояниями, контролируемыми spring-кривой, которую мы создали ранее. Давайте сделаем то же самое с кнопкой «Close».

closeBtn.states.Show =
y: 40
animationOptions:
curve: defaultSpring

closeBtn.states.Hide =
y: -50
animationOptions:
time: .2

Затем мы сохраним некоторые свойства по умолчанию из iOS Guide, которые нам потребуется использовать позже.

origX = iOSGuide.x
origY = iOSGuide.y
origSize = iOSGuide.size
origPos = iOSGuide.screenFrame

Подобно тому, что мы сделали с нашими кнопками «Play» и «Close» выше, мы создадим состояния для iOSGuide и изображения внутри него.

iOSGuide.states.Open =
size: Screen.size
x: 0
y: 0
borderRadius: 0
animationOptions:
curve: defaultSpring

iOSGuide.states.Close =
size: origSize
parent: Page1
x: 23
y: 258
borderRadius: 15
animationOptions:
curve: defaultSpring

iOSGuideImage.states.Expanded =
height: 400
animationOptions:
curve: defaultSpring

iOSGuideImage.states.Initial =
height: 250
animationOptions:
curve: defaultSpring

Добавление текста

Окончательный момент настройки до того, как мы начнем кодить переходы, заключается в добавлении дополнительного контента в iOSGuide, как показано в примере. TextLayer от Framer упрощает это.

articleText = new TextLayer
text: textExample
parent: iOSGuide
x: 25
y: 430
width: Screen.width - 50
fontSize: 17
fontFamily: "SF-Pro-Text-Regular, -apple-system"
lineHeight: 1.75
color: "#000"

headerText = new TextLayer
text: "Core Philosophies"
parent: iOSGuide
x: 25
y: articleText.maxY + 20
width: Screen.width - 50
fontSize: 17
fontWeight: 900
fontFamily: "SF-Pro-Text-Bold, -apple-system"
lineHeight: 1.75
color: "#000"

Переход 1 (открытие события)

Мы хотим, чтобы переход начался при нажатии iOSGuide. Для этого мы собираемся использовать событие onTap.

iOSGuide.onTap ->

Когда это произойдет, мы хотим удалить его из PageComponent и parent его на экране Chapters. Когда он расширяется, он не обрезается своим родительским слоем и появляется выше всего остального. Установив слой iOSGuide по умолчанию родительским для нового слоя в событии изменит его положение на экране, но мы хотим, чтобы переход начинался с того же места, в котором он находился внутри PageComponent. Чтобы сделать это, мы будем использовать одно из свойств iOSGuide, которое мы сохранили ранее, называемое «screenFrame». Во Framer это свойство получает точное положение и размер элемента на экране.

this.parent = Chapters
this.screenFrame = origPos

Пока мы будем использовать «this».

Затем давайте изменим внешний вид строки состояния и поместим под ней iOSGuide. Это, очевидно, необязательно, но при разработке для iOS хорошей практикой является использование как светлых, так и темных версий строки состояния, поэтому при изменении контекста, в котором он отображается, всегда есть хороший контраст.

StatusLight.visible = true
StatusDark.visible = false
this.placeBehind(StatusLight)

Мы будем использовать ранее установленные нами состояния и анимировать iOSGuide и iOSGuideImage для этих состояний.

this.animate("Open")
iOSGuideImage.animate("Expanded")

Чтобы анимировать разные состояния, мы использовали метод. animate () и передавали имя состояния, для которого мы хотим анимировать. Имя состояния всегда должно быть строкой, поэтому оно должно быть заключено в кавычки.

Теперь у нас должен быть переход между экранами. На данный момент, нет способа отменить это. Нам нужно показать кнопки «Close» и «Play». Чтобы сделать это, мы снова будем использовать. animate () и переходим в состояние «Show» для каждого состояния, чтобы оживить их. Мы также разместим их над iOSGuide, чтобы убедиться, что они видны.

closeBtn.animate("Show")
closeBtn.placeBefore(iOSGuide)
playBtn.animate("Show")
playBtn.placeBefore(iOSGuide)

Переход 2 (Закрытие события)

Нам нужен способ закрыть экран статьи и вернуться к главам (Chapters). Чтобы сделать это, мы добавим к кнопке закрытия событие «onTap» и вернем наши компоненты обратно в их начальные состояния.

closeBtn.onTap ->
iOSGuide.animate("Close")
iOSGuideImage.animate("Initial")

StatusLight.visible = false
StatusDark.visible = true

closeBtn.animate("Hide")
playBtn.animate("Hide")

Последнее, что нам нужно сделать — вернуть iOSGuide в PageComponent, когда заканчивается анимация закрытия. Для этого мы установим текущее состояние iOSGuide «Close». Потому, что мы собираемся проверить. onAnimationEnd, когда она прекратит анимацию, но мы не хотим возвращать ее обратно в PageComponent, когда заканчивается анимация открытия.

iOSGuide.onAnimationEnd ->
if iOSGuide.states.current.name is "Close"
this.parent = Page1
this.x = origX
this.y = origY

Мы использовали оператор «if», чтобы проверить, является ли текущее состояние iOSGuide «Close», и если да, сделать что-нибудь. В этом случае, вернуть ее в Page1 в PageComponent и установить ее свойства X и Y обратно в начальные значения внутри Page1, которые мы сохранили в origX и origY ранее в прототипе.

Теперь мы можем нажать на карточку, и мы увидим, как она открывается, а затем мы можем нажать кнопку закрытия, и мы увидим, как она закрывается. Если мы хотим, мы также можем добавить рамку iPhone к нашему прототипу.

Благодарность

Отдельное спасибо John Sherwin и Daniel Nisttahuz за соавторство этой статьи.