인프런 커뮤니티 질문&답변

leo님의 프로필 이미지
leo

작성한 질문수

웹 애니메이션을 위한 GSAP 가이드 Part.02

forEach안에서 gsap을 사용할 때 이벤트가 한번밖에 안걸리는 문제

해결된 질문

작성

·

435

·

수정됨

1

const box=gsap.utils.toArray('.box');

box.forEach(function(item){
item.addEventListener('click',function(){
 gsap.to(item,{
  rotationY:360,
  duration:1,
  ease:'none'
 })
})

})

안녕하세요 강의 잘 보고있습니당

공부하다가 질문이 생겨 문의드려요..

gsap을 forEach안에서 사용해서 애니메이션을 줄려고합니다.
위처럼 코드를 적으면 동작은 잘되는데 클릭이 한번밖에는 안되네요..
이 문제를 해결할 수 있을까요?

답변 1

0

범쌤 님의 프로필 이미지
범쌤
지식공유자

안녕하세요 안미혜님 :)

 

해당 코드에서 html에 .box가 여러개가 있나요?

 

html에 .box가 여러개가 있다면 각각의 박스들을 클릭했을 때 해당 아이템에게 클릭이벤트와 애니메이션이 개별적으로 적용되는게 맞습니다.

 

  1. 같은 대상 (.box가 한개인 경우) 에게 하나의 클릭이벤트를 여러개 거는것과

  2. 여러개의 대상 (.box가 여러개일 경우) 에게 클릭이벤트를 각각의 대상에게 거는건 다른 문제입니다.

 

만약 하나의 대상 (1번과 같이)에게 대상을 클릭했을 때 애니메이션이 여러번 실행되고 싶으신 거라면 이벤트를 한번만 걸고 토글의 형태로 코드를 만들어 애니메이션을 제어해 주셔야 합니다.

 

예시코드)


const box = document.querySelector('.box');

let toggle = false;

box.addEventListener('click',()=>{

  if(!toggle){
    gsap.to(box,{rotation: 360 }) 
  }else{
    gsap.to(box,{rotation: 0 }) 
  }

  toggle = !toggle
  
})

 

 

해당 코드는 삼항 연산자식으로 변경하면 보다 깔끔하게 처리할 수 있습니다.


    const box = document.querySelector('.box');

    let toggle = false;

    box.addEventListener('click',()=>{

      gsap.to(box,{rotation: !toggle ? 360 : 0}) 
      
      toggle = !toggle
      
    })

 

 

여기서 클로저를 사용한다면 보다 안전하게 변수를 관리할 수 있습니다.


    const box = document.querySelector('.box');

    

    
    function boxAnimation(){
      let toggle = false;

      return ()=>{
        gsap.to(box,{rotation: !toggle ? 360 : 0}) 
        toggle = !toggle
      }
      
    }

    box.addEventListener('click',boxAnimation())

 

 

더 나아가 IIFE(Immediately Invoked Function Expression) 패턴과 함수 표현식을 사용한다면 보다 깔끔하게 핸들러 함수를 작성할 수 있습니다.

  const box = document.querySelector('.box');

    

    
    const boxAnimation = (()=>{
      let toggle = false;

      return ()=>{
        gsap.to(box,{rotation: !toggle ? 360 : 0}) 
        toggle = !toggle
      }
      
    })()

    box.addEventListener('click',boxAnimation)

 

 

 

감사합니다 :0

 

 

leo님의 프로필 이미지
leo
질문자

아...ㅠㅠㅠ선생님 너무 감사합니다.
이렇게 자세히 알려주셔서 공부할거 더 늘긴 했지만ㅎㅎㅠㅠㅠ 정말 감사드립니다.
음..저는 여러개의 박스에 각각 이벤트를 걸고 싶어서 박스를 배열로 처리한다음 forEach를 사용하여 각각의 박스에 효과를 적용하려 했었거든요..

html은<div class="container"> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> </div>

이렇게 있습니다.
그래서 box를 개별로 처리한다음 바로 회전되지 않고 클릭하는 요소만 회전되도록 해보고 싶었어요..

클릭을 하면 클릭하는 요소가 제대로 회전이 되는데 한번더 클릭하면 안되는 문제가 있었습니댜.
모든 박스가 한번씨만 클릭 이벤트가 먹히더라구요
다시 클릭하면 안되구요..

혹시 이부분은 해결이 안될까요?

개별 box 부분의 자세한 설명 너무 감사드립니다.

leo님의 프로필 이미지
leo
질문자

const box = document.querySelectorAll('.box');

box.forEach(function(item){
 item.addEventListener('click',()=>{
  console.log(item)
   gsap.to(item,{rotation: 360 })         
})
})

이렇게 코드를 적으면 클릭하는 박스는 한번 제대로 동작이 됩니다 

image 콘솔창에 찍어보면 처음 클릭하는 박스는 제대로 동작이 되구요 클릭했던걸 한번더 클릭하면 콘솔 제일 아래쪽 줄처럼 이미 360도로 돌아갔기 때문에 더 동작이 안되요
저는 클릭할때마다 동작하게 하고 싶거든요

범쌤 님의 프로필 이미지
범쌤
지식공유자

한번 클릭 후 이미 360도가 돌아갔기 때문에 더이상 애니메이션이 작동하지 않습니다

 

그럴경우 애니메이션이 종료 후 애니메이션의 재생헤드를 처음으로 돌려놓는 코드를 작성해 주시거나 일정값(360)만큼 계속 증가하는 코드를 작성해 주시면 됩니다.

 

제가 밖이라 자세한 코드설명은 힘들것 같아서 양해부탁드립니다 ㅠㅠ

gsap.to(item,{rotation:”+=360”}) 으로 작성해보세요

 

 

leo님의 프로필 이미지
leo

작성한 질문수

질문하기