F#8 stateCycle()로 Toggle Switch Button 만들기

좀 있으면 Framer X Beta를 받아볼 수 있다. 이미 받아서 사용하고 있는 사람들도 있다. 인터랙션을 바로 사용 가능하게 하는 라이브러리가 생겼더라. 그걸 바로 끌어다 사용하는 예고편 영상을 보았다. 드래그 앤 드롭을 했을 뿐인데 그냥 움직인다. 나는 그런 걸 수동으로 코드 짜는 재미를 이제야 맛보고 있는데, 동적인 요소를 키트로 만든 라이브러리라니 약간 김이 샌다. 뭐 간편하게 인터랙티브 프로토타입을 구현할 수 있다는 점에서는 어마어마한 장점이 될 거라 생각한다. 그래도 컴포넌트의 동작에 관해서는 직접 코드로 짜 보고 싶었는데, 아쉽다.

그래서 간단하게 toggle switch button을 만들어보았다.

#Layer

먼저 레이어는 토글버튼의 bg와 핸들링 할 수 있는 스위치 버튼의 두 가지다. 이때 버튼의 크기는 고정 좌표로 하지 않고 계산하는 방식을 택했다. 스위치 버튼의 크기에 따라서 toggleBG 의 사이즈도 조절되도록 짜 보았다. toggleBG의 가로사이즈는 switchBtn의 사이즈의 두배에 패딩값의 두 배를 더한 값이다. 그리고 switchBtn의 maxX를 toggleBG width값의 2분의 1로 설정하면, 토글 스위칭의 on/off위치는 toggleBG의 2분의 1기준에서 좌,우로 이동하게 설정하기 편하다.

background = new BackgroundLayer
switchBtn = new Layer
width: 40
height: 40
borderRadius: 40
backgroundColor: “white”
padding = 4
toggleBG = new Layer
width: switchBtn.width * 2 + padding * 2
height: switchBtn.height + padding * 2
borderRadius: switchBtn.width
backgroundColor: “rgba(150, 150, 150, 0.2)”
toggleBG.center()
switchBtn.parent = toggleBG
switchBtn.maxX = toggleBG.width / 2
switchBtn.y = Align.center()

#States

이번에도 역시 stateCycle()을 이용한다. default와 다른 한 개의 state가 필요하므로, 간단하게 bg 컬러만 변경 되도록 설정했다. background의 경우, 디폴트를 제외한 두 가지의 state가 돌도록 했다. 버튼의 애니메이션 옵션에는 time을 짧게 주고, bg는 해가 뜨고 질 때의 느낌으로 조금 느리게 변하도록 했다.

background.states =
day :
backgroundColor: “#70B9DF”
night :
backgroundColor: “#19265A”
toggleBG.states.on =
backgroundColor: “#99CC66”
switchBtn.states.on =
minX: toggleBG.width / 2
toggleBG.animationOptions =
time: 0.3
switchBtn.animationOptions = toggleBG.animationOptions
background.animationOptions =
time: 3

#Events

이벤트는 정말 간단하다. 클릭 시 스테이트가 돌도록 하면 끝. 이때 switchOn이라는 변수를 지정 해주고 시작은 true로 한다.
switchOn = !switchOn 의 의미는 토글의 두 가지 상태가 다른 상황이라는 것에 대한 정의를 내려 주는 것 같다. 같은 버튼이지만 각 state로 전환되었을 때 다른 기능을 한다는 뜻인 듯. designhow라는 사이트에서 해 준 튜토리얼 강의를 보고 알게 되었는데, 스터디를 통해 좀 더 자세히 알아봐야겠다.

switchOn = true
“}”>switchBtn.onClick (event, layer) ->
switchOn = !switchOn
background.stateCycle([“day”, “night”])
toggleBG.stateCycle()
switchBtn.stateCycle()

구현 화면 보러 가기 >

F#7 Layer.stateCycle()로 두더지 잡기

 

F#6을 포스팅하면서 머릿속을 스쳐간 ‘두더지 잡기 게임’을 간단하게 만들어 보았다.

이번에 유용하게 쓴 코드를 세 가지 추려 본다면 이것이다.

Utils.randomNumber()

Utils.delay 숫자, ->

Layer.stateCycle()

#LAYER

레이어는 가로로 3개를 먼저 반복시켜주고, 3개 묶음을 다시 세로로 3회 반복시켜 총 9개의 홀에서 두더지가 튀어나오도록 했다.

for i in [0…3]
gameBox = new Layer
width: 280
height: 100
backgroundColor: “”
y: i * 100
parent: gameArea
for i in [0…3]
realHole = new Layer
width: 60
height: 80
borderRadius: 80
backgroundColor: “”
clip: true
parent: gameBox
x: i * 100 + 10
#hole의 maxY값을 realHome의 높이값으로 지정했다. 이것은 눈속임
hole = new Layer
width: 60
height: 60
borderRadius: 60
backgroundColor: “#AED4CD”
maxY: realHole.height
parent: gameBox
x: i * 100 + 10
hole.sendToBack()
#두더지 얼굴 만들기
moleBody = new Layer
width: 50
height: 100
borderRadius: 65
parent: realHole
x: Align.center
y: Align.bottom(+72)
backgroundColor: “#D56829”
clip: true

 

두더지의 생김새가 매우 간단하기 때문에 프레이머의 코드 탭에서 얼굴을 표현해보기로 했다. 얼굴에는 약간의 하이라이트를 주고 눈썹, 눈, 입 레이어를 추가해 반복시켜주었다. 이때 양쪽 눈썹의 각도와 입의 크기는 Utils.randomNumber() 를 이용해 다양한 표정을 레이어링 해 보았다.

다음은 점수를 표시할 텍스트레이어. F#5에서 공부했던, 클릭 시 증가하는 카운트를 위한 레이어 세팅이다.

count = 0
score = new TextLayer
text: count + ” 마리 잡았다!”
x: Align.center()
y: gameArea.maxY + 40
color: “lightgray”
fontSize: 20
fontWeight: 700
textAlign: “center”

 

#STATES

두더지가 랜덤하게 튀어나오려면 애니메이션에 대한 코드를 어떤 식으로 작성해야 하는 것일까. 반복문은 나의 취약점이다. 반복해 준 레이어를 통에 넣는 순간 어찌할 바를 모르게 된다. 레이어링까지는 간단히 해결 하였는데…그 다음부터 스멀스멀 멘붕이 오기 시작함.

이 9마리 두더지들에게 각각 인덱스 번호를 매겨주어야 하는 게 아닐까? 그리고 튀어오르는 애니메이션 하나를 정의한 다음, 두더지 번호들을 랜덤하게 호출하면 랜덤하게 튀어나오려나? 그럴싸하다고 생각했는데, 그래서 이걸 코드로 어떻게 짜야 하는 것일까?

머리를 굴려보고 굴려보다 우연히 유튜브 강의를 보게 되었다. 강의는 이것 https://youtu.be/hSIdPgCkEBw

stateCycle()이 이렇게 유용하게 쓰이는구나! 그렇다면 지금까지 생각했던 애니메이션 구조를 버리고 이걸 이용해 보도록 하겠다. 두더지가 들어가 있을 때의 상태를 기본으로 하고, 튀어오르는 state를 설정한다. stateCycle()의 기본 사이클은 ‘디폴트와 설정한 값’이다. state의 세팅이 끝났으면, 바로 애니메이트 시켜 준다. 이때 delay값을 1초부터 3초까지 랜덤으로 지정해 놓았으므로, 두더지들이 제각각 튀어오르는 동작은 성공했다.

for i in [0…9]
moleBody_array[i].states.pop =
y: 10
opacity: 1
options:
time: 0.4
curve: Spring(damping: 0.3)
delay: Utils.randomNumber(1,3)
moleBody_array[i].animate(“pop”)

두더지 게임에서는 때리기 전에 숨기도 한다. 그래서 다시 들어가도록 Utils.delay를 이용해 두더지들이 아무 때나 숨도록 하였다. 이때 digtime은 랜덤하게 지정했는데, 그랬더니 희한한 눈속임 기능이 구현되었다. 이미 랜덤한 시간에 튀어오르고 숨고를 반복하고 있는 와중에 또다시 digtime이라는 변수를 설정해 주었기 때문에, 어떤 때는 두더지가 한번에 숨기도 했다. 스터디 시간에는 digtime을 고정값으로 변경해 보았는데, 그때 나오는 결과도 흥미로웠다.

Utils.delay digtime, ->
for i in [0…9]
moleBody_array[i].stateCycle()

#EVENTS

사용한 이벤트는 아래의 한가지다. 간단하게 요약해 보면, 클릭했을 때 state가 바뀌는 것이다. 카운트는 1씩 증가하는데, 두더지가 튀어올랐을 때 때리는 경우에만 카운트가 증가하도록 설정했다. 두더지가 튀어오르는 state를 보면 y값이 10이므로, y가 10이면 카운트를 증가시키는 코드를 넣어 주었다. 그리고 두더지를 때리면 숨어야 하므로, click했을 때 state가 바뀌도록 설정했다. 그리고 애니메이션이 끝나도 다시 튀어올라야 하므로, onAnimationEnd 이벤트를 주고 pop이라는 state로 다시 애니메이트 시켜줬다.

moleBody_array[i].onClick ->
hammer.play()
if this.y == 10
count += 1
score.text = count + ” 마리 잡았다!”
score.color = “black”
this.stateCycle(time: 0.4, curve: Spring(damping: 0.4))
#stateCycle이 끝나면 다시 애니메이션을 시작해줌.
moleBody_array[i].onAnimationEnd ->
this.animate(“pop”)

 

그래서….이 게임은 무한대다. ㅋㅋㅋ

재미있는 요소로 공부하는 것도 좋은 방법이라 생각한다. 하고싶은 걸 만들면서 공부할 수 있으니까 그만큼 성취감도 높아지는 듯.
나의 튜토리얼은 계속 된다. 진정한 GUI 인터랙션을 만들기 전까지는 일단.

구현 화면 보러 가기 >

F#6 medium 박수치기 버튼 만들기

카운트 올리는 코드를 완성하고, 미디엄 박수 버튼에 응용해 보기로 했다.

미디엄의 박수치기 버튼은 일반적으로 사용하는 좋아요 버튼(좋아요/ 좋아요 취소의 두 가지 케이스 토글 스위칭)과는 달리, 내가 마음에 드는 대로 박수치는 횟수를 더해줄 수 있다는 것이 특징이다. 아주 마음에 드는 포스트에는 열 번이고 스무 번이고 박수를 쳐 주는데, 메타포의 의미와도 잘 부합하는 것이 상당히 매력적인 기능이라 생각한다.

#Layer

일단 프레이머 디자인 탭에서는 손 모양을 만들어준다. 미디엄과 같은 모양은 아니지만, 대략 박수를 치는 의미에 접근만 가능할 정도로 만들어 주었다. hands로 이름을 지었다.
화면은 일반 canvas로 사용하고, 애니메이션 영역을 캔버스 전체로 지정해준다. 버튼을 가운데로 정렬시켜주고 카운트가 올라갈 때 기준점을 버튼으로 해 주기 위해서다.
여기서 새로 알게된 점. framer의 design 탭에서 직접 그림을 그리고 나면 반드시 frames 로 그룹핑을 시켜줘야 properties가 적용된다.

animationArea = new Layer
backgroundColor: “”
size: Screen.size
animationArea.center()
clapBtn = new Layer
borderRadius: 50
width: 100
height: 100
backgroundColor: “white”
borderColor: “efefef”
borderWidth: 1
parent: animationArea
clapBtn.center()
#shape은 frames에 넣어줘야 속성이 적용됨.
hands.parent = clapBtn
hands.x = Align.center
hands.y = Align.center

다음으로, 박수 카운트를 표출할 영역을 만들어준다. 버튼을 클릭했을 때 시작점은 버튼의 중심으로 잡아야 하므로 midY는 clapBtn의 midY와 동일하게 잡아주고 clapBtn의 뒤쪽으로 숨김. 카운트 숫자에 대한 표현은 F#5에서 공부한 방법으로 세팅했다.

countBox = new Layer
x: Align.center
width: 40
height: 35
borderRadius: 35
backgroundColor: “3f3cab”
midY: clapBtn.midY
opacity: 0
count = 0
countNum = new TextLayer
text: “+” + count
textAlign: “center”
parent: countBox
color: “white”
fontSize: 12
fontWeight: 800
x: Align.center
y: Align.center
countBox.sendToBack()

지금까지는 애니메이션을 구현할 때 state를 쓰는 방법을 사용했지만 이번에는 new animationLayer를 이용해보았다. DOCS에서 찾으면서 응용하며 공부하는 게 가장 좋은 방법이 아닐까 한다. clapBtn의 애니메이션은 버튼이 확대되었다가 축소되는 것으로, 애니메이션이 끝나면 거꾸로 재생되도록 해 주었다.

clapBtnScaling = new Animation clapBtn,
scale: 1.15
borderColor: “3f3cab”
borderWidth: 1.5
options:
time: 0.2
curve: Bezier.ease
clapBtnDefault = clapBtnScaling.reverse()
# Alternate between the two animations
clapBtnScaling.on Events.AnimationEnd, clapBtnDefault.start

카운트 영역은 fade in 효과로 올라왔다가 0.4초 후 fade out효과로 사라지도록 하였는데 이것은 투명도를 활용했다. y값은 70 씩 감소하도록 설정해주었다.

countRaise = new Animation countBox,
minY : clapBtn.minY – 70
opacity: 1
options:
time: 0.4
curve: Bezier.easeOut
countFadeOut = new Animation countBox,
minY : clapBtn.minY – 70 – 70
opacity: 0
options:
time: 0.5
curve: Bezier.easeIn
delay: 0.4
countRaise.on Events.AnimationEnd, countFadeOut.start

이 버튼에서 잔상이 남는 애니메이션에 대한 states를 세팅한 부분이 있는데, 이번 포스팅에서는 클릭 시 반응에 대해서만 글을 올려 본다. 잔상 효과는 나중에 기회가 있을 때 포스팅 해 보도록 하겠다.

#Events

이제 박수 버튼을 클릭했을 때의 동작들을 구현해본다. countNum이 증가할 때마다 countBox의 패딩을 지정해주고, countBox는 무조건 가운데로 배치되게 설정했다. 클릭할 때 버튼이 살짝 커졌다 작아지는 애니메이션과, 카운트 표출 영역이 솟아오르는 애니메이션을 재생한다. 이때 카운트 숫자는 누를 때마다 1씩 증가하게 설정했다.
모든 애니메이션이 끝나면 다음 클릭 시 원 좌표부터 시작하기 위해 countBox의 minY값과 opacity를 처음 값과 동일하게 세팅한다.

clapBtn.onClick ->
countBox.width = countNum.width + 23
countBox.x = Align.center
clapBtnScaling.start()
countRaise.start()
count += 1
countNum.text = “+” + count
countFadeOut.on Events.AnimationEnd, ->
countBox.minY = clapBtn.minY
countBox.opacity = 0

이렇게 해서 완성했다. 클릭 시의 반응에 대해 작업하다 보니, 왠지 두더지 게임을 만들고 싶어졌다.
두더지 게임을 만들 때는 Lottie를 이용해서 두더지가 망치로 맞을 때(히익 잔인한 느낌 무엇…)의 표정 등을 같이 만들어보면 재미있을 것 같다.

구현 화면 보러 가기 >

F#5 클릭했을 때 숫자 카운트가 증가하는 버튼 만들기

이번에는 Framer로 아주 간단한 버튼 클릭 이벤트를 만들어보았다. 버튼을 클릭하면 카운트가 올라가는 것이다. medium의 박수 버튼을 신명나게 누른 것이 동기가 되었는데, 일단 간단한 코드부터 명확히 한 다음 실제로 박수치기 버튼을 만들어 보려 한다.

Layer, State, Event중에 State는 필요하지 않고 나머지 두 가지에 대해서 세팅했다.

#Layer

너무 간단하기 때문에 글을 쓰는 것 조차 민망하지만, 원하는 결과가 나왔기 때문에 기념으로 글을 남긴다.
일단 레이어는 두 가지만 설정하면 되었다. 버튼과 버튼 안에 들어가는 숫자.

count = 0
btn = new Layer
width: 100
height: 100
backgroundColor: “yellowgreen”
borderRadius:100
btn.center()

먼저 변수 count를 0으로 설정한다. 굳이 먼저 설정한 이유는 마음이 급해서 였는데, 지금 생각해보니 맨 앞에 두길 잘 한 것 같다. 변수나 배열 등은 맨 앞에 두는 게 정돈되어 보이는 것 같다. 실제로 countNum 위에 count변수를 정의 해 보았더니, 무언가 중간에 끼어있는 느낌이 들었다. 이제 나만의 코드 짜는 패턴이 생기기 시작하는 것 같다.

countNum = new TextLayer
text: “+” + count
parent: btn
textAlign: “center”
width: btn.width
color: “white”
fontSize: 23
fontWeight: 800
x: Align.center
y: Align.center

다음으로, 숫자를 표현할 TextLayer를 생성하고 속성을 입힌다. 많은 속성들 중 가장 중요했던, text.
text는 +기호와 함께 카운트 변수의 숫자를 넣도록 하였다. count에 0을 대입하였으므로, 표출되는 text는 +0 이다.

#Events

이제 버튼을 클릭했을 때 일어나는 동작만 구현하면 된다만, 나는 여기서 어찌할 바를 몰라서 onClick -> 까지만 적고 멘붕이 왔다고 한다. 사실 생각했던 코드는 count++였다. 그러나 count++로는 오히려 오류만 발생했다. 도대체 뭔지 아직도 모르겠다. 이럴 땐 뭐다? 검색. 카운트를 늘리는 코드를 열심히 검색했다. Docs에서는 내가 원하는 문형은 나오지 않았다.  framer count++ (++는 어디서 봐 가지고 ㅋㅋㅋ)로 검색을 해 보았다. 내 나름대로 최대한 결과가 나올 만한 검색어를 입력해 본 것이다. 다행히도 facebook group에서 비슷한 코드를 발견했다.

btn.onClick ->
# print count
count += 1

count를 1씩 증가시킨다.
하지만 역시 아무 일도 일어나지 않았다. print를 해 보니, 다행히도 count 는 1씩 증가하고 있었다.
아무 일도 일어나지 않는 이유는 무엇일까?

btn.onClick ->
# print count
count += 1
countNum.text = “+” + count
btn.backgroundColor = Utils.randomColor()

아, 이유는 다름아닌, 버튼을 클릭했을 때 countNum에게 어떤 동작을 일으켜라, 라는 요청을 하지 않았기 때문이었다.
맙소사, 이렇게 하나씩 알게 되는구나. 버튼을 눌렀다는 걸 명확히 표시하기 위해, 클릭했을 때 버튼의 bg컬러를 랜덤하게 바꿔주는 코드도 추가하였다.
그리하여 아래와 같은 버튼을 만들었다.

이번 시도를 통해서 적어도 어떤 방식으로 코드를 짜야 화면이 돌아가는지 조금은 알게 되었다. 역시, 어떤 일이든 과정이 있어야 결과가 있다. 또 한 가지 깨달은 것은, 이런 어설픈 실력으로 그동안 앱 전체의 목업을 만들고 있던 내가 신기하다는 것이다.

구현 화면 보러 가기 >

이제 medium 의 clap버튼을 만들 수 있을 것 같다.

 

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”)

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

구현화면보러가기 >