F#4 lottie animation을 Framer에 적용하기

Lottie Animation에 대해서 정리한 글에 이어서, 이번에는 lottie animation을 활용하여 Framer에 적용해 보겠다.

아래 데모 영상의 애니메이션은 회사 프로젝트 중 어그러진 작업물이라 부분적으로 올려 본다.
음성 명령과 사운드검색을 장면 전환 없이 한 화면에서 동작해볼 수 있게 프로토타이핑 한 것이다.

그럼 시작.

첫번째로 Illustrator에서 오브젝트를 제작한 후 After Effect에서 애니메이션을 제작, BodyMovin 플러그인을 이용하여 json data파일을 뽑아낸다. 하나는 음성을 듣는 중이라는 애니메이션, 또하나는 음표의 잔상이 남는 애니메이션이다. 두 개의 json date 파일은 작업하고 있는 Framer프로젝트의 images폴더 안에 넣어 둔다.

프레이머의 디자인 탭에는 음성 명령(말풍선 메타포, iconVoice), 사운드 검색(음표 메타포, iconSound)의 두 가지 오브젝트와, 둘을 묶어준 영역인 searchBtn 을 준비한다. 참고로 이것은 스케치앱에서 copy & paste 한 것이다.(여기서 잠깐, 이게 종종 영역만 붙고 오브젝트 자체는 붙이기가 되지 않는 경우가 있다. 왜 이러는지는 모르겠다.)

https://github.com/72/lottie-framer
위의 링크에서 LottieLayer.coffee를 다운로드 받은 후, 작업할 프레이머 프로젝트의 modules 폴더에 넣고, 프레이머 코드탭 상단에 아래의 문구를 넣어준다.

{LottieLayer} = require ‘LottieLayer’

그다음 배운대로 Layer, State, Event를 차례대로 세팅한다.

#Layer

디자인탭에서 오브젝트를 미리 준비했기 때문에 레이어링은 많이 필요하지 않았다.
오브젝트들이 있을 bg영역을 만들어주고, searchBtn이라는 그룹을 화면의 가운데에 정렬해준다.

bg = new BackgroundLayer
searchBtn.center()

다음으로, Lottie Animation으로 만든 json파일들을 연결 해 준다.
LottieLayer모듈을 넣었기 때문에 LottieLayer라는 새로운 공구를 쓸 수 있는 듯하다.
아래 속성 중에 direction이라는 속성이 있어서 테스트 해 보았는데, 숫자 값이 -일 경우에는 애니메이션이 역재생 되는 듯한 모습이 보였다. 역시 하라는 대로 하면 뭐가 뭔지 모른다능. (이것은 스터디 후 명확하게 적어보도록 하겠다.)

voiceRecog = new LottieLayer
x: Align.center
y: Align.center
name: “voiceRecog”
path: “images/voice_button.json”
autoplay: true
loop: true
speed: 0.6
direction: 1
parent: searchBtn
width: 120
height: 120
soundRecog = new LottieLayer
x: Align.center
y: Align.center
name: “soundRecog”
path: “images/sound_button.json”
autoplay: true
loop: true
speed: 1.2
direction: 1
parent: searchBtn
width: 110
height: 110

#State

말풍선 버튼의 state는 아래의 세 경우이다.
1. 기본상태 2.스스로를 tap했을 때 3.음표 버튼을tap 했을 때
1번 기본 상태가 필요한 이유는, 음표 버튼을 tap한 후 다시 말풍선 버튼을 눌렀을 때 제자리로 돌아와야 하기 때문이다. 스스로를 tap했을 때는 부모 레이어인 searchBtn을 기준으로 center로 위치하도록 하고 버튼의 사이즈를 키워준다. 음표 버튼을 tap했을 때는 말풍선 버튼이 반투명한 회색으로 바뀌고 사이즈도 줄어들도록 하였다.

#음성인식, 사운드 검색 버튼 스테이트 세팅
iconVoice.states =
default:
x: 47
y: 1
width: 90
height: 90
grayscale: 0
opacity: 1
scale: 1
tap:
x: Align.center
y: Align.center
width: 120
height: 120
grayscale: 0
opacity: 0
soundTap:
grayscale: 100
opacity: 0.4
x: 20
y: + 25
scale: 0.75

사운드 검색 버튼(음표)도 동일하게 세팅한다.
두 버튼 모두 애니메이션이 필요하므로, 애니메이션 옵션은 아래와 같이 세팅한다.

iconVoice.animationOptions =
time: 0.7
curve: Spring(damping: 0.7)

앞서서 음성 명령, 사운드 검색의 애니메이션에 이름을 지정해둔 바 있다.
voiceRecog, soundRecog 이 두 가지 항목을 animations라는 이름의 통에 묶어 준다.
그리고 이 두 애니메이션의 state를 지정해 주고, 두 개 모두 off상태로 변경해준다(보이지 않아야 함)

animations = [voiceRecog, soundRecog]
for i in [0…2]
animations[i].states =
on:
opacity: 1
off:
opacity: 0
animations[i].animationOptions =
time: 0.4
curve: Spring(damping: 0.6)
animations[i].stateSwitch(“off”)

#Events

레이어와 스테이트에 대한 세팅이 끝났다. 이제 양 쪽 버튼을 눌렀을 때 벌어지는 이벤트에 대해 세팅해 보겠다. 자신을 눌렀을 때에 대한 state값인 “tap”으로 animate시켜준다. 0.1초 후 음성인식에 대한 애니메이션을 보여주기 위해 on상태로 바뀌도록 해 준다.

#음성명령 버튼 눌렀을 때 모션
“}”>iconVoice.onTap ->
this.animate(“tap”) #설정한 스테이트로 애니메이팅
iconSound.animate(“voiceTap”)
soundRecog.animate(“off”)
“}”>Utils.delay 0.1, ->
voiceRecog.animate(“on”)

사운드 버튼도 동일하게 세팅하면 완성!

구현화면보러가기 >

F#번외편 lottie로 animation 만들기

요즘 프레이머를 다루면서 관련된 툴이나 기능들을 많이 보게 된다. 프레이머 자체에서도 모션 구현이 가능하지만 더욱 정교하고 엣지 있는 애니메이션을 만들어 넣어보는 것도 괜찮을 것이다. 그래서 요즘 아주 솔깃한 Lottie Animation에 대해서 글을 써 보려 한다.

Lottie 란?

Lottie란 오픈소스 모바일 라이브러리다. json data파일을 만들어낼 수 있도록 도와주는 플랫폼이다. 독일 영화 감독이자 실루엣 애니메이션의 선구자인 로띠 라이네거(Lotte Reiniger)의 이름을 따서 지어졌다고 한다. 가장 잘 알려 진 그녀의 영화로는 가장 오래된 장편 영화인 ‘아흐메드 왕자의 모험’이 있는데, 이 영화는 월트 디즈니의 장편 백설 공주와 일곱 난쟁이를 10년 넘게 앞선다고 한다.

실루엣 애니메이션 – 아흐메드 왕자의 모험. 이거 왜 어렸을 때 본 것 같은 느낌이지?

앱이나 웹에서 아래와 같이 움직이는 피드백을 주는 애니메이션이 많아졌다.

  • 트위터에서 좋아요를 눌렀을 때 뽁 터지는 하트
  • 인스타에서 좋아요를 눌렀을 때 띠용~하는 하트
  • 페이스북에서 ‘축하해’라는 텍스트를 입력했을 때 빵 터지는 폭죽과 스르륵 올라가는 풍선들
  • 카카오페이로 송금했을 때 동전이 촤라랑 떨어지는 애니메이션

위 애니메이션들은 어떻게 제작 되었을까? 여러 회사들의 애니메이션 제작 방법이 궁금하기 전에, 지금 내가 다니는 회사에서는 움직이는 이미지를 gif로 제작한다. 몇십 장의 이미지를 만들어 그 시퀀스를 순서대로 재생하는 방식으로 애니메이션을 표현한다. 굉장한 리소스를 잡아먹는다는 치명적인 단점이 있다. 레퍼런스를 찾으면서 벡터의 느낌이 물씬 풍기는 자연스럽고 부드러운 애니메이션에 대해서 너무나도 궁금했었는데, 때마침 lottie는 정말 반가운 정보가 아닐 수 없었다.

Lottie는 Android와 iOS, 웹에서 Adobe After Effects에서 작업한 애니메이션을 Bodymovin이라는 플러그인을 사용하여, 영상 파일 대신 json이라는 데이터 파일을 생성하도록 지원한다. 아래 링크를 타고 들어가면 많은 사람들이 만들어놓은 애니메이션의 샘플을 확인할 수 있다.

https://www.lottiefiles.com/

 

Lottie애니메이션의 장점

  1. gif 애니메이션보다 훨씬 작은 용량으로 제작되어 리소스를 대폭으로 줄일 수 있다.
    gifs는 용량이 무거울 뿐 아니라, 고정된 크기로 렌더링 되기 때문에 해상도 대응이 어렵다.
    json data파일로 제작하면 해상도에 구애받지 않는다는 큰 장점이 있다.
  2. 디자이너가 개발자에게 정교한 애니메이션을 요구하지 않고도 애니메이션을 만들어 제작할 수 있다.
    에펙에서 플러그인을 사용하여 랜더링 버튼 클릭만으로 json파일로 내보낼 수 있다.
  3. gif로 만들어진 애니메이션을 수정할 때 처음부터 scene로 일일이 수정할 필요가 없다.
    기본적으로 에펙의 작업 파일을 가지고 있으니, 수정 후 다시 한 번 랜더링을 거치면 끝이다.
  4. 이건 개인적으로 생각하는 가장 큰 장점. 디자이너가 만들어도 동작이 어설프지 않다.

Lottie애니메이션의 단점

  1. 안드로이드 저사양 단말에서는 Lottie로 애니메이션을 구현할 수 없다고 한다.
    그러나 저사양 단말에서는 협의를 통해 움직이는 이미지 대신 정적인 이미지를 넣으면 될 것이다.
    사양에 맞게 분기를 태우면 되므로, 크게 문제 되지는 않을 것으로 생각된다.
    그 이외의 단점은 무엇인지, 연구가 필요함.

animation json파일 만들기

  1. 아래 준비물을 준비한다.
    Lottie를 플랫폼으로 하는 Bodymovin ae plugin
    리소스를 만들 Adobe illustrator
    애니메이션을 제작할 Adobe After Effects
  2. 애니메이션의 소스를 만든다.

    간단하게 star.ai를 만들어 보았다. 소스를 만들 때는 기본적으로 ai파일을 제작할 Adobe illustrator가 필요하며, sketch를 사용하는 경우에는 작업한 파일을 SVG로 내보내기 한 다음 다시 illustrator로 불러와 ai파일로 만들어야 한다. 최종 산출물로 ai파일을 소스로 준비한다.
  3. Adobe After Effects 를 켜기 전에 Bodymovin 플러그인을 설치한다.
    설치할 플러그인의 경로는 아래와 같다.
    https://github.com/airbnb/lottie-web 
    After Effects의 window > Extension에 bodymovin 메뉴가 보이면 설치가 완료 된 것이다.
  4. Adobe After Effects에 제작한 ai파일을 불러온 후, 컴포지션을 생성한다.
    생성은 컴포지션 아이콘으로 스윽 드래그 한다.

  5. 컴포지션으로 만들어 준 벡터 레이어를 shape로 만들어준다.
    shape로 변환을 해야 실질적인 애니메이션 작업이 가능하다.
  6. 재미있고 신나게 애니메이션을 제작한다.
    airbnb에서는 뷰티풀한 매직을 하라고 써 있었던 것으로 기억한다.
    나는 그냥 가볍게 별이 마구 돌도록 만들어주었다.
  7. after effects의 Window > Extensions > Bodymovin 을 연다.
    랜더링 할 경로를 지정한 뒤 rander버튼을 클릭한다.
    프로그레스 바가 채워지기를 기다리기도 전에 랜더링이 끝난다.
  8. 지정한 경로를 확인하여, json파일이 생성 되었다면 디자인 완료!
    2KB짜리 애니메이션이 만들어졌다. 행복.
    json이 도대체 뭐냐? 생소한 말이다. 하지만 혹시 그거 아닌가? 스케치의 크래프트를 사용하면 거기에 json data를 활용하는 기능이 있다. bodymovin을 사용하여 만들어진 json을 열어보면 아래와 같은 복잡 미묘한 숫자들이 나온다. 이걸 읽으며 애니메이션이 표현되는 듯하다. 개발자 분도 뭔가 비슷한 설명을 해 주셨던 것 같은데 역시 나는 디자이너기에 무슨 말씀인지 잘 모르겠고…..
  9. json파일을 개발자 분에게 전달 후 화면 테스트한다.
    회사에서 애니메이션을 만들어 개발자에게 테스트를 부탁 하였는데, “한마디로 ‘이미지’넣을 자리에 ‘json’을 넣는 거라고 보면 돼요” 라는 답변을 얻었다. 몹시 명쾌한 답변 주셔서 대단히 감사합니다. 앱 내에서 아주 부드럽게 잘 돌아가는 애니메이션 아이콘을 확인할 수 있었다. gif가 아닌, 위와 같은 좌표값을 가진 애니메이션이다. 파일을 확인해보면, 용량이 매우 작음을 알 수 있다.

이 페이지는 내가 실제로 애니메이션 작업을 하면서 참고한 http://airbnb.io/lottie/after-effects/getting-started.html  페이지를 해석하여 간략하게 정리한 것이다.
도움말이나 샘플 등, 자세한 설명은 http://airbnb.io/lottie/에서 확인 가능하다.


https://www.lottiefiles.com/에서 앱을 다운로드 하면 Lottie로 만든 애니메이션 파일이 돌아가는 모습을 미리 확인 가능하다. 사이트 내에서도 json파일을 드래그해 확인할 수 있다. 이 글 다음으로는 내가 lottie를 이용해 만든 버튼과, 버튼을 눌렀을 때의 피드백을 프레이머에서 구현해 본 이야기를 적어 보도록 하겠다.

로띠를 지원하는 툴로 Adobe After Effects 외에도 Haiku라는 툴이 있다고 한다.
에펙보다는 훨씬 간편해보이긴 하는데 이런 툴들을 다 사용하기는 어려우니, 선택해서 사용하면 될  것 같다. https://www.haiku.ai/

F#3 Tab Bar 버튼의 활성/비활성 상태 인지하기

tab bar 작업화면
이번에는 구현했던 tab bar에서 한단계 깊이 들어가보았다. 각각의 메뉴를 눌렀을 때 불이 켜지는 동작을 만들었다. 그런데 이중 가운데 메뉴는 다른 화면과 달리 팝업이 아래에서 올라오는 구조이다. popup을 닫으면, 현재 보이는 화면에 대한 버튼의 불이 켜져 있어야 한다. 감이 잡힐듯 말듯. 한 번 구현에 성공했던 화면이었기에 처음부터 다시 만들면 쉽게 작성 가능할 거라 생각했으나 오산이었다. 그러나 이번 경험으로 개념 이해에는 한발짝 더 다가간 것 같다.

이 화면에서 나는 화면의 stack 구조를 어떻게 짜야 할 지가 가장 힘들었던 것 같다. 먼저 각 메뉴를 눌렀을 때 뜰 다섯개의 화면이 필요한데, 팝업을 제외한 나머지 화면은 하단 tab bar보다 아래 뎁스에 위치해야 하므로 가장 위에는 tab bar가, 그 아래에는 각 메뉴의 화면들을 놓으면 될 거라 생각했다. 그러면 flow밖에 tab bar를 빼 놓고, flow안에는 화면 네 개를 놓고, 가운데 화면은 tab bar위로 어떻게 쌓냐능????????

그래서 생각한 것이, 세번째 버튼을 눌렀을 때는 탭바가 아래로 사라진 후 팝업이 스윽 위로 뜨면 되지 않을까? 였다. 그렇게 하면 세번째 화면이 flow 아래 있더라도 눈속임이 가능할 것 같으므로.

먼저 Tabs의 state를 셋팅하고, 기본 상태는 화면 하단에 그대로 보이도록 “up”으로 스테이트를 전환시켜준다. 3번 버튼을 누르면 states는 “down”으로 바꿔줄 것이다.

59
60 Tabs.states =
61 up:
62 maxY: Screen.height
63 down:
64 y: Screen.height
65 Tabs.animationOptions =
66 time: 0.5
67 curve: Spring(damping: 0.7)
68
69 Tabs.stateSwitch(“up”)

이렇게 해서, 화면을 눌렀을 때 각 페이지가 뜨고 세 번째 버튼을 누르면 팝업이 뜨는 동작까지 구현 완료. 이제 팝업에서 내리기 화살표를 눌렀을 때, 지금 보이는 화면의 버튼에 불이 들어오게 해 보겠다. 왠지 ‘지금 보이는 무언가’가 일치했을 경우라는 어떤 그런 조건을 활용할 것 같은 느낌에, docs에서 current로 검색을 해 보았다. 핳. 그 ‘무언가’를 찾은 것 같다. 바로 응용해 봄.

 

140
141 closeBtn.onTap ->
142 screens[2].animate(“down”)
143 Utils.delay 0.3, ->
144 Tabs.animate(“up”)
145 Utils.delay 0.5, ->
146 # print flow.current.name
147 for i in [0…5]
148 if flow.current.name == names[0]
149 btnGnbs[0].animate(“on”)
150 menuTexts[0].animate(“on”)
151 else if flow.current.name == names[1]
152 btnGnbs[1].animate(“on”)
153 menuTexts[1].animate(“on”)
154 else if flow.current.name == names[3]
155 btnGnbs[3].animate(“on”)
156 menuTexts[3].animate(“on”)
157 else if flow.current.name == names[4]
158 btnGnbs[4].animate(“on”)
159 menuTexts[4].animate(“on”)

오오 됐다. flow.current.name으로 설정한 이유는, 현재 화면과 버튼간의 관계에서 뭔가 일치시키고 싶은 명확한 요소가 필요했기 때문이다. 그래서 flow를 부모로 하는 각 스크린마다 name property를 지정해주었다. 뭔가 엄청 날림공사인 듯 하지만, 날림으로 많이 해 보는 게 좋다고 스승께서 말씀 하셨으니 나쁜 건 아니라고 생각한다. 어쩌다 보니 코드가 160줄이나 나와 버려서 줄일 방법을 고민하긴 해야겠지만.

구현 화면 보러 가기 >

F#2 Tab Bar 구현하기

취미생활로 끝인 줄만 알았는데, 어느새 회사에서 프레이머로 목업을 제작중인 나를 발견 후덜덜. 거기에 더하여 이 작업에 집중할 수 있도록 다른 업무가 배제되었다.(꿀) 6주 클래스 이후로 본격적인 앱 프로토타입을 만들어낸다는 게 쉽지 않지만, 날마다 차근차근 구현에 성공함으로써 성취감을 느끼고 있다.

그중 가장 뿌듯했던 것은, 몇 번의 도전 끝에 Tab Bar 활성탭/비활성탭의 구조를 구현했다는 것이다. 프레이머가 출시된 지 최소 4년은 넘은 만큼 탭바에 대한 오픈소스는 곳곳에서 찾을 수 있었다. 그러나 소스를 받아서 흉내를 내 보아도 응용이 되지 않았다. 어느 곳에서 틀린 건지 구분하는 건 능력 밖의 일이었다. 그래서 따라해본 소스는 전부 삭제하고 탭바 영역만 따로 떼어 내가 배운 지식을 토대로 처음부터 만들어 보았다.

먼저 배열을 세팅한다. sketch파일을 import했고, 버튼과 메뉴 텍스트의 레이어명을 배열에 순서대로 추가 하였다.

1 btnGnbs = [btnGnb1, btnGnb2, btnGnb3, btnGnb4, btnGnb5]
2 menuTexts = [menu1, menu2, menu3, menu4, menu5]
3 hotSpots = [] #버튼의 영역 지정
4

반복문을 이용하여 다섯개의 버튼, 메뉴명 텍스트에 대한 states를 셋팅한다. 활성탭은 on, 기본상태는 off로 이름을 지어 주고 각각의 properties를 작성한다. 여기에서는 활성탭을 불투명하게, 비활성 탭은 투명도를 30% 주었다.

5
6 for i in [0…5]
7 btnGnbs[i].states =
8 off:
9 opacity: 0.3
10 on:
11 opacity: 1
12 menuTexts[i].states =
13 off:
14 opacity: 0.3
15 on:
16 opacity: 1
17 btnGnbs[i].animationOptions =
18 time: 0.2
19 menuTexts[i].animationOptions =
20 time: 0.2

버튼의 불이 켜질 때 스르륵, 켜 지도록 할 것이므로 animationOptions를 사용하여 시간을 지정한다.
그리고 아래와 같이 모든 아이콘의 불을 끄고, 첫번째 메뉴만 불을 켜 준다.

21
22 btnGnbs[i].stateSwitch(“off”)
23 menuTexts[i].stateSwitch(“off”)
24 btnGnbs[0].stateSwitch(“on”)
25 menuTexts[0].stateSwitch(“on”)
26

다음으로 hotspot이라는 이름으로 버튼 영역을 만들어 준다. 다섯개의 영역이 만들어졌다.

27
28 hotspot = new Layer
29 parent: Tabs
30 width: Screen.width / 5 – 10
31 height: Tabs.height
32 x: 5 + i * Screen.width / 5
33 backgroundColor: “transparent”
34 index: i 
35 hotSpots.push(hotspot)

이제 이 영역을 눌렀을 때, 각각의 버튼에 불이 들어오도록 하는 #Events를 셋팅한다.
여기서 막히기 시작함.
분명 현재 버튼의 번호라든가 뭔가 일치하면 불이 들어오게 하면 될 텐데, 뭘 어떻게 일치시켜야 할 지. 며칠동안 수도 없이 오픈 소스를 찾아보았지만 배웠던 방식과 달라 제대로 구현되지 않았다. 그러다 docs에서 찾게 된 layer.index 라는 것을 응용하여, hotspots의 각각의 인덱스를 i로 지정해주었다. 5개의 hotspot의 번호가 만들어졌다. 순서대로 1,2,3,4,5. 버튼과 메뉴 텍스트의 번호와 일치할 방법을 찾았다.

36 hotSpots[i].onTap ->
37 # print this.index. 인덱스를프린트해 봄.
38 for i in [0…5]
39 if i == this.index
40 btnGnbs[i].animate(“on”)
41 menuTexts[i].animate(“on”)
42 else
43 btnGnbs[i].animate(“off”)
44 menuTexts[i].animate(“off”)

i 라는 변수를 다시 5개 반복시켜 i와 hotspot의 index 가 일치하면 i 에 해당하는 버튼과 텍스트는 “on”상태로 애니메이션을 실행, 그렇지 않을 경우에는 “off”로 애니메이션 실행.
이렇게 하여 구현에 성공 하였다.

구현화면 보러 가기 >

F#1 Utils.modulate를 이용한 텍스트 두께 조절

디자이너가 프레이머를 사용하기 위해서 가장 필요한 것은 ‘개념 이해’라고 생각한다. 지난 수업의 2주차 정도 까지는 플래시 액션 스크립트나 html 코딩의 경험이 도움이 되어 크게 어려움이 없었는데배열과 함수? 뭐였더라, 아무튼 ‘통’에 담는 얘기가 나오기 시작하면서 멘붕은 시작되었다. 왜 담는 거야 도대체? 처음에 쉽게 코드를 짤 수 있었던 이유는 그동안에 해 왔던 것들을 기반으로 개념을 확실히 이해하고 있기 때문일 것이다. 그 뒤로는 처음 접해보는 ‘언어’가 주는 장벽이 시작되는 것이다. 반복적으로 작업해보면 개념이 잡힐 날이 올 거라 생각하며 하나 하나 차근차근 공부를 해 보려 한다.

첫번째로 구현해 본 화면은, 슬라이더를 움직임에 따라 텍스트의 두께가 달라지는 인터랙션이다.
전자책의 설정 화면에서 글자 크기를 조절하는 것에서 착안하였다. 사용한 코드는 배열과 반복문, 드래그모듈레이터이다.
전체적인 플로우를 머릿속으로 그려본 후 Layer, State, Event 차례대로 세팅한다.

#Layer

레이어링은 디자이너가 굉장히 쉽게 접근할 수 있다. 특히 html/css를 다룰 줄 아는 디자이너라면 훨씬 쉽게 다가올 것이다.
먼저 검은색의 백그라운드 레이어를 추가하여 기본 bg를 생성해 준다.
그다음은 3개의 텍스트를 꺼내 쓸 배열을 세팅한다. 한국어, 영어, 일본어를 차례로 쓸 것이니 순서대로 적어 묶어 놓는다. texts라는 변수명에 할당한다.

이 세 가지 텍스트는 사이즈, 두께가 같으므로 반복문을 이용하여 같은 스타일의 폰트 3개를 반복시킬 것이다. fonts라는 빈 통을 준비한다. 반복문에서 생성된 텍스트 레이어를 담을 통이다.

1 bg = new BackgroundLayer
2 backgroundColor: “black”
3
4 texts = [“가”, “A”, “あ”]
5 fonts = []
6

이제 fonts라는 통에 담을 텍스트레이어 3개를 만들어 준다. 반복문의 순번은 0부터 시작한다.
폰트에 대한 구체적인 특징을 세팅한 뒤, 생성된 3개의 폰트를 fonts라는 통에 담아준다.
아직 스타일을 지정할 때 “”를 어느 부분에서 써야 하는지는 이해가 가지 않는 상태다.
이건 framer docs를 찾아보면서 작성한다.

7 for i in [0…3]
8 font = new TextLayer
9 width: Screen.width/3
10 text: texts[i]
11 fontSize: 120
12 fontWeight: 100
13 x: i * Screen.width/3
14 y: Align.center()
15 color: “white”
16 textAlign: “center”
17
18 fonts.push(font)

이제 핸들러를 만들어 준다. 컨트롤 할 수 있는 바 형태를 만든다.

19 progressBar = new Layer
20 width: 300
21 height: 20
22 borderRadius: 20
23 x: Align.center
24 y: 500
25 backgroundColor: “342562”
26

ball이라는 변수명으로 컨트롤할 수 있는 원형 오브젝트를 생성한다.
이때 parent는 progressBar로 지정해주고, y값은 프로그레스바의 중간으로 위치하여 행을 맞춰준다.

27 ball = new Layer
28 parent: progressBar
29 width: 30
30 height: 30
31 y: Align.center()
32 backgroundColor: “white”
33 borderRadius: 30
34

ball의 드래그를 설정한다. 세로 드래그는 필요하지 않으므로 불가능하도록 설정, 드래그의 범위는 프로그레스바의 width값과 같게 해 준다. 그 영역을 넘어서까지 드래그 되진 않도록 설정한다.

35 ball.draggable.enabled = true
36 ball.draggable.vertical = false
37 ball.draggable.constraints =
38 x: 0
39 width: 300
40 height: 0
41 ball.draggable.overdrag = false
42

#State
스테이트를 사용할 것이 없다고 판단하여 따로 지정해 주지 않았다.

#Events

이 화면에서는 ball이 좌 우로 움직이면서 텍스트의 두께가 변화한다. 그러므로 ball의 x값의 변화를 인지하고, x값의 범위, 폰트 두께변화의 범위를 알려준다. 공구함의 modulate를 써서 아래와 같이 기재한다. 이때 3종 텍스트 두께를 모두 변화 시키기로 했으므로, 반복문을 이용한다. 폰트를 3개 생성해 담아놓은 fonts 통을 쓴다.

43 ball.on “change:x”, ->
44 # print this.x 대략적인 ball의 x값을 알아보기 위해서는 print를 해 보는 것이 좋다.
45 for i in [0…3]
46 ballXRange = [0, 270]
47 fontWeightRange = [100, 900]
48 fonts[i].fontWeight = Utils.modulate(this.x, ballXRange, fontWeightRange)
49
50

Utils.modulate(우리가 이용할 값, 알고 있는 것의 범위, 결과값의 범위) = 볼의 x를 이용하여, 볼의 x값의 변화에 따라, 폰트의 두께가 변화한다. 로 생각하면 됨.

구현화면보러가기 >

이렇게 하여 첫번째 화면이 구현되었다.
ebook어플리케이션의 설정화면을 프레이머로 구현해 본다면 굉장히 재미있을 것 같다.