Framer Tips — 자주 발생하는 문제 해결하기

Jung Young Lee
Learning Curve of JY
11 min readJul 30, 2016

이 프로젝트는 최초 Obkim 과 함께, 우리가 알고 있는 자주 막히는 문제들을 모아서 가볍게 공유해보자 — 라고 시작했으나, 더 많은 사용자들이 각자의 노하우를 모아보면 좋을 것 같은 생각에 Dropbox Paper 에 위키 형태로 열어놓았던 글입니다. 이미 시간이 많이 흘러 새로운 팁이 더이상 추가되지 않는 상태라, 미디엄쪽에 살짝 편집해서 공유해 봅니다. Framer JS Korea 페이스북 그룹의 많은 분들이 자발적으로 참여해주셨고, 그 덕에 한글 문서가 전무했던 1년 전, 각자의 상황에서 고군분투 하시던 많은 분들에게 큰 도움이 되었을 것이라 생각합니다.

Dropbox 쪽 원본 문서는 아직 살아있습니다. 지금이라도 나의 프레이머 팁을 추가하고 싶으시면, 하단 링크에서 언제든지 참여해주세요.

들어가며

프레이머로 코드를 작성하다 보면, 단순한 프로토타입을 만들려고 했는데 간단한 버그에 막혀 시간을 다 버릴때가 있다. 알고나면 너무 간단해서 허망했던 것들. 혹은 프로그래밍에 대한 지식이 조금 더 필요했던 것들. 프레이머에서 이미 적절한 메소드를 제공하고 있던 것들. 그동안 작업하며 마주쳤던 이런 이슈들을 한번 모아보기로 했다. 내가 삽질했던 건 당신도 삽질할 가능성이 높다. 지혜를 모아 삽질을 방지하고 우리의 피같은 시간을 아껴보자! 당신이 알고 있는 새로운 팁을 이 문서에 추가하는 것도 적극 환영이다. 혹은 더 쉽고 간단한 방법이 있다면 역시 코멘트하자.

1. 기본적인 몇 가지 커피스크립트 문법

http://coffeescript.org

#JavaScrpit / CoffeeScript=== / is
!== / isnt
! / not
&& / an
|| / or
true / true, yes, on
false / false, no, off
this / this, @
in / of
없음 / in
Math.pow(a,b) / a**b
Math.floor(a / b) / a//b
(a % b + b) % b / a %% b

2. 모든 사이즈의 디바이스에서 잘 보이게 만들고 싶을때

  • 최상단에 wrapper 를 만들고, 이미지 사이즈에 따라 스케일을 조절한다.
#화면 크기와 동일한 wrapper를 만든 다음 모든 레이어의 부모 레이어로 설정한다.
wrapper = new Layer
width: 750
eight: 1334
#부모 레이어의 originX와 originY를 0으로 설정
wrapper.originX = 0
wrapper.originY = 0
#프로토타입을 작업한 디바이스의 가로폭이 750px일 경우
wrapper.scale = Screen.width/750

3. 레이어의 순서를 자유롭게 변경하고 싶다

  • 코드의 작성 순서대로 레이어의 인덱스가 결정되는데, 기본 메소드를 활용해 쉽게 변경할 수 있다.
  • bringToFront(), sendToBack(), placeBehind(), placeBefore() 참고
  • 단, 레이어의 부모관계가 다른 경우 위 코드로 인덱스를 변경할 수 없다.

4. 레이어에 접근이 안된다. 분명 name 속성을 줬는데…

  • 개똥같지만 name으로는 접근이 안된다. 원래 그렇다.
myLayer = new Layer
name: myLayer2
# Output : Can’t find variable myLayer2
print myLayer2

5. 여전히 레이어에 접근할 수 없다면

  • 혹시 함수명이랑 겹치는건 아닌지 확인해본다.
  • 동일한 이름의 레이어가 저 높이 어딘가에 있는건 아닌지 확인해보자. 코드가 길어지면 가끔 겹친다.

6. 페이지를 품은 스크롤을 만들었더니 사방으로 미끄러진다

  • 중첩된 스크롤 / 페이지를 사용할때 둘 모두에게 diretionLock = true를 주면 한 방향으로만 움직이게 된다.
myScroll = new ScrollComponent
myPage = new PageComponent
parent: myScroll
# 한방향으로만 스크롤 페이징되도록 제어
myScroll.directionLock = true
myPage.directionLock = true

7. 스크롤에 사용하는 이벤트 Move와 Scroll은 어떻게 다른가?

  • Move는 레이어의 이동만 감지하므로, 마우스 휠을 사용한 Scroll을 인식하지 못한다.
  • Scroll은 스크롤만 감지하므로, momentum으로 이동중인 상태를 Scroll로 인식하지 못한다.

8. 클릭해서 닫는 레이어를 만들었더니 안쪽 버튼이 클릭이 안된다

  • 상당히 여러번 질문을 받았던 내용이다. 클릭이벤트가 중복되면 작동하지 않기 때문에 발생한다.
  • 딤 레이어의 opacity를 0으로 만든 이후에 scale = 0 으로 처리하면 좋다.
myBtns = new Layer
myDim = new Layer
myBtns.on Events.Click, ->
print “Hello”
myDim.on Events.Click, ->
myDim.animate
properties:
opacity: 0
# opcity가 0이 된 이후에 scale도 같이 0으로 변경
myDim.on Events.AnimationEnd, ->
if myDim.opacity is 0
myDim.scale = 0

9. x, y 외에 레이어의 위치를 표현할 수 있는 방법

#최소값을 기준으로
minX, minY
#최대값을 기준으로
manX, maxY
#중간값을 기준으로
midX, midY

10. 매번 레이어를 불러 올 때마다 sketch. psd.과 같이 임포트 형식을 적어야 하나?

# sketch를 사용할 경우 레이어 이름을 변수로 바로 사용한다.
Utils.globalLayers(sketch)
# Photoshopt을 사용할 경우 레이어 이름을 변수로 바로 사용한다.
Utils.globalLayers(psd)

11. 파일 전체의 애니메이션 커브를 변경하고 싶다면

# 파일 전체의 애니메이션 커브에 “spring”을 적용한다.
Framer.Defaults.Animation = curve: “spring”

12. 스케치, 포토샵에서 import 할 때 에러나는 상황

  • 폴더의 이름에 한글이 있는 경우 에러
  • 폴더의 이름 중 프레이머에서 사용되는 예약어가 있는 경우 에러
  • 스케치 아트보드 이름이 한글인 경우 에러
  • 가끔씩 텍스트 레이어가 살아있을 때 에러. (비트맵으로 병합 시키면 해결되기도 함)

13. 불러온 레이어에 하나의 state만 추가하고 디폴트 화면을 state로 유지하고 싶다

  • state를 추가한 다음 switchInstant로 변경해 두고, 기본 제공하는 “default” state를 활용한다
layerA.states.add
off:{y:Screen.height}
layerA.states.switchInstant(“off”)Handler.on Events.Clicks,->
layerA.states.switch(“default”)

14. for 반복문으로 layer를 동적으로 생성하고, 다시 접근하고 싶다

  • Array를 공부할 때가 됐다.
myArr = []for i in [0..10]
newLayer = new Layer
myArr.push(newLayer)

15. for 반복문에서 만든 i값에 접근하고 싶다

  • myLayer.idx = i (idx는 임의의 이름) 이렇게 별도의 프로퍼티에 미리 저장해두는 방식이 많이 사용된다.
  • Array의 indexOf() 메소드로도 접근 가능하다.
myArr = []for i in [0..10]
myLayer = new Layer
x: 120*i
myLayer.idx = i
myLayer.on Events.Click,->
print this.idx
print myArr.indexOf(this)
myArr.push(newLayer)

16. for 반복문으로 클릭 이벤트를 줬는데, 마지막 버튼만 클릭이 된다

  • 이벤트가 발생하기 전에 이미 for문이 모두 돌아서 발생하는 이슈.
  • 이벤트를 할당할 때, this 를 활용하면 이벤트가 발생한 객체에 접근할수 있다.
for i in [0..10]
newLayer = new Layer
y: i*120
# Output is 1200
newLayer.on Events.Click, ->
print newLayer.y
# Output is Clicked layer’s y position
newLayer.on Events.Click, ->
print this.y

17. Screen은 뷰어의 디바이스를 의미하고, screen은 작업중인 모니터 스크린을 의미한다

# output: 1334(750*1334 iPhone6)
print Screen.height
# output : 1440(1920*1440 monitor)
print screen.height

18. 영상을 프로토타입에 넣었더니, 모바일에서 자동으로 Media Player가 연결된다

  • Frameless등의 전용 뷰어 어플리케이션을 사용하는 것이 가장 쉬운 해결책이다.
  • 많은 수의 동영상을 사용할 경우 Frameless에서도 문제가 발생한다는 제보.

19. Event.Tap 탭 위치 가져오기 (Click 이벤트는 안됨, Tap, TapStart, TapEnd 됨)

  • 새로 추가된 Tap 이벤트와 나머지 제스처 이벤트들은 터치한 곳의 좌표를 알아낼 수 있다.
  • 헌데 event.point.x 값은 모바일에서 잘 나오는데, Framerjs Studio에서 보면 이상하게 나온다.
  • 이걸 Framerjs Studio에서 제대로 확인할 수 있게 만들어 둔 메소드가 있다. Utils.convertPointFromContext(event.point, layer, true, false)
  • 앞에 두개의 파라미터만 정해주면 됨. event.point 랑 기준좌표가 될 레이어 layer를 넣어주자.
bg = new BackgroundLayer
backgroundColor: “#e3e2f8
bg.on Events.TapStart, (event) ->
print “폰에서 x:” + event.point.x + “, y:” + event.point.y
screenCoords = Utils.convertPointFromContext(event.point, bg, true, false) print “맥북 or pc 에서 x:”+Math.floor(screenCoords.x) + “, y:” + Math.floor(screenCoords.y)

20. sketch 에서 artboard 에 작업했을때 content 짤리는 현상

  • sketch 에서 6s artboard 추가해서 아래로 엄청긴 컨텐츠를 가진 화면을 구성
  • 임포트 했을때, 엄청 긴 컨텐츠가 화면 바깥쪽을 다 짤려있는 현상
  • FramerJS 에서도 이부분 질문이 많음
  • Koen의 답변 “Sketch clips all graphics outside of the artboard” -Dec 2015
  • 해결책: 결국 해당 아트보드의 높이를 컨텐츠를 커버할정도로 길게 하면 안짤림

21. States의 Animation Option을 States 개별적으로 설정하는 법

  • 글로벌 Animation Option은 모든 States에 적용되는데, 아래와 같이 하면 원하는 특정 States의 Animation option만 설정할 수 있다.
# Switch to stateB with a spring curve
layerA.states.switch(“stateB”, curve: “spring(400, 30, 0)”)
# Switch to stateB with an easing curve
layerA.states.switch(“stateB”, time: 1, curve: “ease”)

22. Utils.interval을 삭제하는 방법

  • Utils.interval() 함수를 핸들러에 저장해두고, clearInterval()을 사용해서 삭제한다.
  • clearInterval 메소드는 Framer Studio 안에서 하이라이트처리가 없는데, 잘 작동한다.
# clearInterval ExampleintervalHandler = nullstartInterval = ->
intervalHandler = Utils.interval 1, ->
myFunc()
endInterval = ->
clearInterval(intervalHandler)

23. 프로토타입 전체를 리프레시하고 싶다.

  • 프로토타입을 심플하게 그냥 처음부터 보고싶을 때가 있다.
  • 일일이 변수 및 state를 default 처리하기 귀찮을 때 좋은 방법.
# reload current prototype
location.reload()

마치며

1년 전부터 조금씩 모아본 팁이라, 그사이 Framerjs Studio 업데이트로 인해서 문법이 살짝 변한 부분이 있으니, 참고하면 좋을것 같다. ( ex : 이벤트 shortcut 같은게 당시에는 없었음 ) 코드의 이상한 부분이나, 동일 이슈를 해결할 수 있는 더 좋은 방법이 있으면 언제든지 의견 부탁드린다.

--

--

Jung Young Lee
Learning Curve of JY

LINE UI 디자이너. 프로토타이핑과 인터랙션에 관한 글을 씁니다.