2011-01-18 2 views
12

Brad Larson's answer here과 같이 애니메이션 그룹 접근에 가장 적합한 애니메이션 효과의 경우 입력에 따라 애니메이션을 진행해야합니다. 특히 감지 된 터치의 터치 및 위치. touchesMoved를 처리하기가 쉽고 모든 터치에 대해 요소의 위치를 ​​설정하지만 코어 애니메이션 접근 방식처럼 매끄럽지 않습니다.시간이 아닌 입력 값 (터치)을 기반으로 한 iPhone 애니메이션

그루브 트랙에 대리석이 있다고 상상해보십시오. 한 방향이나 다른 방향으로 어떤 속도로든 어떤 위치로도 대리석을 밀어 넣고 싶습니다. 애니메이션은 터치에 반응하여 경로를 따라 시각적 요소를 움직여 이와 같이해야합니다. CAKeyframeAnimation은 경로 비트를 정확히 가지고 있지만 항상 경과 된 시간에 프레임 간 전환을 기반으로하고 다른 모든 요소가 아니라 한 방향으로 전환을 원합니다.

1 월 31 일 업데이트 - 지금까지의 모든 답변에 감사드립니다. 그러나 아무도 문제를 해결하지 못했습니다. 옵션을 선택하기 위해 드래그되는 원형 메뉴가 있습니다. 그것들 모두는 함께 움직일 필요가 있습니다. 회전 변환이 적용된 뷰와 역 회전 변환이 서브 뷰에 적용된 뷰를 사용하여 그 주위를 돌아 다니며 아이콘이 모두 적절한 관람차 방향으로 회전합니다. 아이콘이 약간 난해한 경로를 따라 움직이는 것이 더 낫습니다 ... 대리석 설명은 내가하려고하는 것을 분명히하려는 시도입니다. 그루브에서 모든 여행을 격퇴하는 방향으로 움직이는 자석을 상상해 보는 것이 더 나을 것입니다. 하나와 그 이웃이 움직이면서 지나갈 때 자석이 움직이는 방향으로 움직이는 것은 아닙니다.

바로 지금이 문제는 원이 하나 인 간단한 경로를 따르는 것이지만 실제로 속도 나 방향과 관련된 계산없이 터치로 제어되는 위치는 임의의 경로를 따라 오브젝트를 움직이는 방법을 알고 싶습니다.

+0

흠, 이것은 대중적인 질문이되었습니다. Pivot의 대답은 정확하며 질문 이후 작성된 코드에서 잘 작동합니다. –

답변

7

레이어 트리에서 hierarchical nature of timelines을 사용하여 원하는 것을 얻을 수 있습니다. 을 구현하는 객체는 CAAnimationCALayer을 모두 포함하며 부모로부터 시간 공간을 상속하며, 이는 배율 변경, 이동 및 반복을 통해 수정할 수 있으며 자식으로 전파 할 수 있습니다. 레이어의 speed 속성을 0.0으로 설정하고 timeOffset 속성을 수동으로 조정하면 해당 레이어 (및 모든 하위 레이어)를 일반적인 시간 개념에서 분리 할 수 ​​있습니다. 당신이 경우에 할 거라고 무엇

는 함께 모든 메뉴 항목은 자신의 위치를 ​​애니메이션의 애니메이션을 정의하는 당신의 시간에서 t 적절한 timeOffset에와, tCGPath을 원하는 각 애니메이션은 항목을 적절히 배치합니다. 애니메이션에서 beginTime의 0.0은 애니메이션이 레이어에 추가 된 시점부터 시작하는 것으로 해석되므로, t 을 0.0으로 설정해야 할 수도 있습니다. ε> 0.0이다.

CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; 
animation.beginTime = 1e-100; 
animation.duration = 1.0; 
animation.fillMode = kCAFillModeBoth; 
animation.removedOnCompletion = NO; 
animation.path = path; 
animation.calculationMode = kCAAnimationPaced; 
animation.timeOffset = timeOffset; 
그러면 응답
0t 1을 (단지 이러한 메뉴 항목을 포함하는) 상위 층에 0.0 speed 속성을 설정 t 사이 값의 timeOffset 업데이트하려는

귀하의 터치 이벤트에.

이 접근법에는 두 가지주의 사항이 있습니다. 이 레이어 하위 트리에서 시간 속성을 가져 왔으므로 다른 속성을 동시에 애니메이션으로 만들 수는 없습니다. 또한, 빠른 플릭을위한 해안 동작을 원한다면, 아마도 스스로 앞으로 시간을 움직일 필요가있을 것입니다.

+0

좋은 생각! 터치 위치에 애니메이션을 정확하게 바인딩하지 않아도 필요한 수준의 컨트롤을 제공 할 것이므로 받아 들여야합니다. timeOffset을 조작하여 같은 일에 매우 가깝게 만들 수 있어야합니다. –

+0

터치 위치와 애니메이션 진행 간의 관계가 선형 인 경우 애니메이션의 beginTime 및 duration을 선택하여 터치 위치의 관련 구성 요소를 timeOffset으로 전달하고 Core Animation의 시간 - 진행 매핑이 해당 관계를 적용하도록 할 수 있습니다 너를 위해서. – Pivot

1

iOS 4.0 이상을 타겟팅하는 경우 new block based class methods을 사용하여 view 개체의 애니메이션 가능한 변경을 시작할 수 있습니다. 그래서 터치 이벤트에서 당신은 뷰의 속성에 애니메이션 변화를 시작할 수 있습니다

[UIView animateWithDuration:1.0 animations:^{ 
    yourView.alpha = 0.0; // fade out yourView over 1 second 
}]; 

N.B.보기의 다른 속성 (위치 등)을 변경하기 만하면됩니다. 당신이 아이폰 OS의 이전 버전을 표적으로하는 경우가 애니메이션 블록을 만들 수있는 UIView beginAnimationscommitAnimations 방법을 사용해야합니다

@property frame 
@property bounds 
@property center 
@property transform 
@property alpha 
@property backgroundColor 
@property contentStretch 

:

[UIView beginAnimations:nil context:context]; 
[UIView setAnimationDuration:1.0]; 
yourView.alpha = 0.0; 
[UIView commitAnimations]; 

을 당신이보기에 다음과 같은 속성이 방법으로 애니메이션을 적용 할 수 있습니다 이 물건은 정말 잘 작동하고 일단 사용을 시작하면 중독되지 않도록 조심해야합니다. ;) 코멘트

업데이트 :

당신은 터치 이벤트의 위치로 대리석의 위치를 ​​바인딩 할 수 있습니다. touchesEnded 이벤트를 받으면 애니메이션 블록을 사용하여 대리석 위치를 애니메이션으로 만들 수 있습니다.

+0

네,하지만 문제는 기간과 아무 관계가 없기를 바라는 것입니다. 대리석을 생각해보십시오. 내가 아무 짓도하지 않으면 아무것도하지 않는다. 내가 천천히 밀어 넣으면 천천히 움직이고, 빨리 움직이면 빨리 움직입니다. 속도를 빨리 돌린 후 갑자기 멈 추면 속도가 느려지고 멈출 때까지 계속 굴러 있어야합니다. 시간 접근 방식이 이것을 허용하지 않는 것처럼 보입니다. CAKeyframeAnimation을 사용하여 아름다운 매끄러운 애니메이션을 만들었지 만 실행을 설정하고 안락함을 쉽게 설정하는 것 이외에는 제어 할 수 없습니다. –

+0

아직 문제가 있습니다. 객체의 위치는 터치의 위치가 아니며 경로에 있어야합니다. 접촉의 스트로크는 접촉이 올바른 시점에서 일어날 때 물체에 움직임을 부여합니다. 개체는 경로를 따라야합니다.또한 위치를 계산하고이를 명확한 방법으로 수행하는 것은 위치 계산이 고비용이되거나 오래된 iOS 기기에서 특히 원활하지 않을 때 특히 그렇습니다. –

+0

@ adam-eberbach 아! 너의 의도를 알 겠어. 이 문제를 일으키는 사건 간의 보간법입니다. 나는 그것에 대해 생각할 것이다. 확실히 사소하지 않음 :) – RedBlueThing

1

속도 = 거리/시간. 이동 된 터치와 시간에 따라 지연을 시도해 볼 수 있습니다. touchesBegan과 touchesEnded 메소드 사이의 시간을 계산할 수 있습니다.

0

나는 당신이하고 싶은 것을 정확히 이해하고 있지만 ... 왜 사용자의 손가락이 어디에 있든 대리석을 그리지 않는 이유는 무엇입니까? 애니메이션이 필요하지 않습니다. 사용자가 이동 한 후에 대리석을 계속 움직이려면 기세 개념을 유지하고 그 대리석을 움직여서 속도를 줄여야합니다. 당신은 그것을 위해 CoreAnimation이나 타이머를 사용할 수 있습니다.

0

저는 터치 감동으로 속도 계산을하고 블록을 타이머를 통해 변경할 수있는 로컬 변수에 추가 할 것입니다.

즉, 움직이는 터치에서는 이전 속도의 방향을 염두에두고 속도 계산을합니다. 접촉이 끝나면 '대리석'이 번역 된 블록을 발사하여 속도를 떨어 뜨립니다. 사용자가 대리석을 다시 움직이고 로컬 변수를 수정하면 터치의 방향에 따라 대리석의 애니메이션 속도를 높이거나 속도를 늦추거나 방향을 변경합니다.

관련 문제