Framer: блоки в цикле

Framer: блоки в цикле

Семеон Бобошко (t.me/semeonboboshko)

Началось!

Я наконец-то добрался до CoffeeScript и Framer. В общем-то, это то, ради чего создавался канал.

Не смотря на то, что в начале этого года я проходил пилотный курс Антона Карташова по Framer, мне пришлось вспоминать очень много всего. Да и одним курсом все нужные знания не получить. И чтобы с чего-то начать, я попросил ребят из Learn Framer подкинуть мне простенькую задачку. Хочу сказать им спасибо за задачу и помощь с кодом.

Задача звучала примерно так: необходимо нарисовать блок размером 256 х 64 с текстом внутри. Блок должен быть в виде класса и вызываться с помощью menu_link = New Link. При наведении на блок должен срабатывать hover. Также блок должен повторяться в цикле 5 раз и в каждом отдельном блоке должен быть разный текст.

Я выполнил всё, кроме того, чтобы сделать блок в виде класса. К сожалению, я пока ничего не знаю про классы.

Перед тем как рассказать про код, можно посмотреть получившийся прототип: https://framer.cloud/mmYdl

https://framer.cloud/mmYdl

Важно помнить, что все прототипы Framer корректно работают только в WebKit-браузерах.


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

Utils.insertCSS("@import 'https://fonts.googleapis.com/css?family=Roboto:300,400,700';")

Цифры в конце ссылки — это подключаемые начертания: Light, Regular и Bold. Я решил подключить на всякий случай всё.

Эти переменные хранят в себе HEX-код цветов:

yellow = new Color("fac112")
white = new Color("FFFFFF")
black = new Color("000000")
blackShadow = new Color("rgba(0,0,0,0.1)")

Переменная blackShadow дополнительно хранит в себе свойства альфа-канала (прозрачности). Я решил записать цвета в переменны по нескольким причинам.

Во-первых, так будет проще использовать нужные цвета.

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

Параметры анимации, записанные в переменную:

curveSpring = "spring(300,20,50)"

От этих параметров зависит то, как будет себя вести объект во время анимации, которому присвоена эта переменная.

Тут я говорю, что цвет фона — жёлтый:

bg = new BackgroundLayer
 backgroundColor: yellow

Тут у меня два массива (шутка про два стула):

buttons = []
words = ["Index 0", "Index 1", "Index 2", "Index 3", "Index 4"]

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

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

for i in [0..4]
 buttons[i] = new Layer
  width: 256
  height: 64
  x: Align.center
  y: 100 + i * 100
  borderRadius: 3
  backgroundColor: white
  animationOptions:
   curve: curveSpring
 
 title = new TextLayer
  text: Utils.randomChoice(words)
  parent: buttons[i]
  fontFamily: "17px Roboto"
  color: black
  textAlign: "center"

 title.center()

 buttons[i].states.a =
  scale: 1.2
  shadowY: 5
  shadowColor: blackShadow
  shadowBlur: 10

 buttons[i].states.b =
  scale: 1
  shadowY: 0
  shadowColor: blackShadow
  shadowBlur: 0

 buttons[i].onMouseOver (event, layer) ->
  layer.states.next("a")

 buttons[i].onMouseOut (event, layer) ->
  layer.states.next("b")

Объявление цикла и указание количества итераций:

for i in [0..4]

Я уже как-то писал, что отсчёт начинается с 0, а не с 1.

Затем, создаётся основной слой — buttons:

 buttons[i] = new Layer
  width: 256
  height: 64
  x: Align.center
  y: 100 + i * 100
  borderRadius: 3
  backgroundColor: white
  animationOptions:
   curve: curveSpring

Из интересного тут два момента. Во-первых, buttons[i] = new Layer — теперь это новая переменная с блоками из массива. Более того, не нужно даже писать что-нибудь вроде buttons.push block, чтобы блоки отправились в массив. Всё делается автоматически.

Во-вторых, y: 100 + i * 100 — делает отступ от каждого последующего блока в 100px.

Настройки текстового слоя:

title = new TextLayer
  text: Utils.randomChoice(words)
  parent: buttons[i]
  fontFamily: "17px Roboto"
  color: black
  textAlign: "center"

 title.center()

parent: buttons[i] — здесь назначается родительский объект. Это нужно для того, чтобы текст всегда был внутри блока и дублировался вместе с итерациями цикла.

text: Utils.randomChoice(words) — случайным образом извлекает индекс из массива. Таким образом, на каждом блоке будет разный текст. Если перезагружать страницу с прототипом, то можно заметить, как меняется текст на одном и том же блоке.

Это states:

 buttons[i].states.a =
  scale: 1.2
  shadowY: 5
  shadowColor: blackShadow
  shadowBlur: 10

 buttons[i].states.b =
  scale: 1
  shadowY: 0
  shadowColor: blackShadow
  shadowBlur: 0

Они нужны для того, чтобы хранить в себе параметры анимации. У меня их два: states.a — отвечает за hover на блок. states.b — отвечает за то, когда курсор убрали с блока.

А это обработчики событий:

 buttons[i].onMouseOver (event, layer) ->
  layer.states.next("a")

 buttons[i].onMouseOut (event, layer) ->
  layer.states.next("b")

onMouseOver — обрабатывает hover, а onMouseOut — обрабатывает событие, когда курсор убрали с блока.


На этом пока всё. Весь прототип занимает 52 строки. Возможно, кажется, что его реализовать было просто, но это не совсем так. Я потратил на это несколько дней. Скорее всего, времени ушло бы больше, если бы в некоторых моментах мне не помогли ребята из Learn Framer. Но сложно будет не всегда, а только в начале. 😆


Также вы можете присылать мне свои идеи для прототипов и задавать вопросы. Можно это сделать напрямую (@boboshko) или через моего бота (@BoboshkoRobot).

Report Page