Приложение к Фреймер-кейсу 2: Функции setGradient() и setRealTime()

Саша Окунев
/designer
Published in
4 min readJan 6, 2018

В этом посте мы проанализируем, как интегрируется SVG в Фреймер и как задать реальное время в прототипе.

Начало здесь:

Шаг 14. Градиенты

А здесь начинается самый хардкор. Можно просто скопировать весь код этого шага, счастливо использовать функцию setGradient() и никогда так и не узнать, что такое дефы и как именно Фреймер высасывает цвета из слоя и применяет их к графикам.

Чтобы графики выглядели не так плоско, на них используются градиенты. Они присутствуют в режиме дизайна в виде отдельных слоёв:

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

Сохраним все три слоя градиентов в массив:

gradients = [g1, g2, g3]

На этот раз в массиве будут храниться не только названия слоёв вроде “g1”, а объекты слоёв целиком. Убедиться в этом можно так:

print g1

В консоль попадёт объект типа Layer:

<Layer id:1 name:g1 (175, 0) 50x50>

Подробнее о том что такое объекты расскажет всё тот же Руслан.

Я заостряю на этом внимание, потому что на этом шаге мы будем работать с объектом градиента.

Пишем функцию setGradient()

Она будет иметь два аргумента:

setGradient = (gradientLayer, pathName) ->

Первый аргумент — объект слоя градиента. Второй — имя SVG-пути, на который будем натягивать градиент.

Внутри функции мы вытащим из объекта gradientLayer дочерний объект gradient (тип Gradient). Для этого нужно создать безымянный объект, который имеет такую же структуру. Команда print подсказывает, что Gradient имеет два свойства: start и end.

Создаём безымянный объект с этими свойствами:

{ start, end }

В него из свойства gradient у слоя gradientLayer вытянем начало и конец:

setGradient = (gradientLayer, pathName) ->{ start, end } = gradientLayer.gradient

Таким образом, мы получили две переменные, которые содержат цвет в формате RGB. Чтобы передать его в SVG-код, нужно сконвертировать его в формат HEX.

Пример белого цвета в RGB и HEX:

{r: 255, g: 255, b: 255} → "FFFFFF"

Чтобы сконвертировать цвет, используем функцию toHex().

К результату добавим символ #, который нужен в SVG-коде для обозначения HEX-цвета:

start = “#” + start.toHex()end = “#” + end.toHex()

В переменную angle сохраняем нужный угол наклона градиента:

angle = 90

Теперь создаём слой-контейнер pattern типа SVGLayer, в котором напишем SVG-код градиента. В дальнейшем мы будем применять этот код в качестве паттерна для каждой линии графика.

pattern = new SVGLayer

Он имеет единственное свойство svg, в котором хранится весь SVG-код.

Поскольку SVG-код многострочный, нам нужно использовать тройные кавычки, чтобы передать определённый фрагмент как многострочное строковое значение:

pattern = new SVGLayer
svg:
"""
здесь можно писать svg-код
"""

Внутри них пишем код svg-элемента:

<svg></svg>

В него мы поместим SVG-элемент градиента:

<linearGradient></linearGradient>

У градиента будут два параметра, id и gradientTransform. id –это идентификатор, по которому Фреймер будет находить нужный паттерн из трёх. В нём присутствует имя пути pathName. Будет три паттерна, которые будут иметь id pattern-outer, pattern-mid и pattern-inner.

id="pattern-#{pathName}"

Через параметр gradientTransform мы зададим нужный угол в 90 градусов из переменной angle:

gradientTransform="rotate(#{angle})"

Чтобы сделать начальную и конечную точку, внутри <linearGradient> будем использовать тег <stop>:

<stop offset="0%" stop-color="#{start}"/><stop offset="100%" stop-color="#{end}" />

Весь SVG-код выглядит так:

Теперь сохраняем SVG-элемент в переменную по названию pathName, как уже делали раньше. Он потребуется нам, чтобы натягивать на него паттерн.

SVGPathElement = Layer.select(pathName).path

Конструкция url() позволяет обратиться к градиенту-паттерну через defs. Это способ использовать один объект как паттерн для другого. Подробнее про defs — в документации MDN.

В переменную stroke кладём деф-ссылку на нужный паттерн по id.

stroke = "url(#pattern-#{pathName})"

Наконец, задаём атрибут stroke через функцию setAttribute():

SVGPathElement.setAttribute("stroke", stroke)

Функция setGradient() готова. Теперь с помощью неё настраиваем все градиенты циклом:

for pathName, i in pathNames  setGradient(gradients[i], pathName)

Теперь SVG-путь с именем outer получит в качестве заливки pattern-outer, который, в свою очередь, берётся из слоя g1.

Весь код шага 14:

Шаг 15, последний. Оживляем часы

Пишем функцию setRealTime().

setRealTime = () ->

Cоздаём объект типа Date

  date = new Date

Вытягиваем из него минуты и часы.

  minute = date.getMinutes()
hour = date.getHours()

Если число меньше 10, добавляем в начало 0. Например: 03.

  if hour < 10 then hour = "0" + hour 
if minute < 10 then minute = "0" + minute

Наполняем текстовый слой realTime:

  realTime.text = "#{hour}:#{minute}"

Через 30 секунд обновляем время, рекурсивно вызывая функцию. Таким образом, время в слое realTime всегда будет актуальным.

Utils.delay 30, ->
setRealTime()

При загрузке прототипа вызываем функцию в первый раз:

setRealTime()

Полный код шага 15:

Я веду Скетч-дизайнер, канал о дизайне интерфейсов в Скетче, плагинах и горячих клавишах. Также пишу о дизайн-системах, проектировании и UI-анимации в Фреймере.

--

--

Саша Окунев
/designer

Дизайн-лид в Kaspi.kz. Автор проекта /designer.