Lecture 7: ViewModifier Animation
# Animation 골든룰!
- 애니메이션은 변화가 발생했을 때만 일어난다!
View
가 이미UI
에 들어가 있는 상태에서ViewModifier 의 인자
가 바뀌었을 때
Shape
이 바뀌었을 때
UI
내부의View
가 생기거나 사라질 때UI
상의View container
에 추가되는 경우UI
상의View container
에서 삭제되는 경우- if-else, ForEach 문
# 애니메이션을 구현하는 3가지 방법!
.animation(Animation)
View Modifier
를 이용한implicit
한 방식duration
,delay
,repear
,curve
등을 직접 지정할 수 있음.animation
앞의 모든ViewModifier
들에 대해 애니메이션이 적용된다container
에 적용 시 내부의 모든View
에 분배되므로, 가장 최하단의 자식View
혹은 독립적으로 작동하는View
에 주로 적용
Text("👻")
.opacity(scary? 1 : 0) // (O) animated
.animation(Animation.easeInOut(duration: 1) // easeInOut -> curve!
.rotationEffect(Angle.degrees(upsideDown ? 180 : 0)) // (X) animated
withAnimation(Animation) { }
함수를 이용한explicit
한 방식- 여러 개의 변화가 발생했을 때 전부에 대해 애니메이션 효과를 추가
explicit
애니메이션은implicit
애니메이션을 오버라이딩 하지 않음!
withAnimation(.linear(duration: 2)) {
// do something that will cause ViewModifier/Shape arguments to change somewhere
}
- UI 상의
Container
에View
를 새로 추가/삭제하는transition
- 작동 원리는 한 쌍의
Viewmodifier
가 변화하는 것 - 즉, 변화 이전
modifier
과 변화 이후modifier
한 쌍의 인자가 변화하는 것을 나타낸 게 애니메이션! ViewBuilder
내부의ForEach
혹은if-else
문을 통해 가능implicit
방식과 달리container
에 적용 시 분산되지 않고 해당container
자체에 적용됨
- 작동 원리는 한 쌍의
# 애니메이션 작동 원리
- 애니메이션 시스템이 애니메이션의 시작부터 끝까지의 과정을 작은 조각으로 분할한다
shape
혹은ViewModifier
가 시스템에게 자신 내부의 어떤 컨텐츠가 애니메이션화되어야 하는 지 알려준다
- 애니메이션 시스템이 애니메이션 구현을 위해
shape
혹은ViewModifier
를 다시 호출해 단계에 따라 적절한 명령을 내린다.
# var animatableData
- 이러한
shape/ViewModifier
는AnimatableModifier
의animatableData
변수를 통해animation 시스템
과 상호작용!
- 위에서 보다시피 양방향으로 상호작용하기 때문에
animatableData
는 읽기와 쓰기가 모두 가능get
: 애니메이션 시스템이 애니메이션의 시작점/끝점을 호출set
:shape/ViewModifier
에게 애니메이션 시스템이 그려야할 조각을 알려주는 것
# Cardify
content
를 받아서 카드화한View
를 반환하는 커스텀ViewModifier
만들기
var body: some View {
GeometryReader { geometry in
ZStack {
Pie(startAngle: Angle(degrees: 0 - 90), endAngle: Angle(degrees: 110 - 90))
.padding(DrawingConstants.circlePadding)
.opacity(0.4)
Text(card.content)
.font(Font.system(size: 32))
} // 카드화 할 content 를 담고 있는 View
.cardify(isFaceUp: card.isFaceUp)
}
}
- 카드를 만드는 데 필요한 정보만 받아와서 구현!
struct Cardify: ViewModifier {
var isFaceUp: Bool
func body(content: Content) -> some View {
ZStack {
let shape = RoundedRectangle(cornerRadius: DrawingConstants.cornerRadius)
if isFaceUp {
shape.fill().foregroundColor(.white)
shape.strokeBorder(lineWidth: DrawingConstants.lineWidth)
content
} else {
shape.fill()
}
}
}
private struct DrawingConstants {
static let cornerRadius: CGFloat = 10
static let lineWidth: CGFloat = 2.5
}
}
// 호출을 쉽게 하기 위한 extension! syntax sugar:)
extension View {
func cardify(isFaceUp: Bool) -> some View {
self.modifier(Cardify(isFaceUp: isFaceUp))
}
}
# .font() 는 애니메이션 적용이 불가한 ViewModifier
# 왜 짝이 맞는데 돌질 못하니...
- 두 번째 카드의 경우 회전해야하는 이모지 즉,
content
가 카드를 뒤집음과 동시에 UI 상에 처음 나타나게 되므로 이미isMatched
인 상태에서 처음 등장해 애니메이션 효과를 줄 변화가 없다...! 따라서 골든룰에 위배되어 애니메이션 효과가 발동하지 않는다!
- 따라서 다음과 같이
content
는 항상 존재하게 하되opacity
를 조절하는 방식으로 바꾸어주었더니 해결되었다!
struct Cardify: ViewModifier {
var isFaceUp: Bool
func body(content: Content) -> some View {
ZStack {
...
if isFaceUp {
shape.fill().foregroundColor(.white)
shape.strokeBorder(lineWidth: DrawingConstants.lineWidth)
} else {
shape.fill()
}
content.opacity(isFaceUp ? 1 : 0) // 수정 부분!
}
}
...
}
☀️ 느낀점
- 애니메이션 효과가 알쏭달쏭하게 느껴진다...개념 파트만 다시 들어봐야할 것 같다.
# Animation
- only changes can be animated
- ViewModifier arguments
- Shapes
- The existence (or not) of a View in the UI
-
A change to a ViewModifier's arguments ahs to happen after the View is initially put in the UI
== only changes in a ViewModifier's arguments since it jointed the UI are animates -
A View coming on-screen is only animated if it's joining a container that is already in the UI
-
A View going off-screen is only animated if it's leavinf a container that is staying in the UI
-
ForEach and if-else in ViewBuilders are common ways to make Views come and go
how do you make an animation go?
- implicitly: by using view modifier .animation(Animation)
- explicitly: by wrapping withAnimation(Animation) {} around code that might change things
- by making View be included or excluded from the UI
Implicit Animation
- mark a view so that all the ViewModifier argumemnts that precede the animation modifier will always be animated!
Text("👻")
.opacity(scary? 1 : 0) // (O) animated
.animation(Animation.easeInOut)
.rotationEffect(Angle.degrees(upsideDown ? 180 : 0)) // (X) animated
Explicit Animation
- Explicit animations create an animation transaction during which all eligible changes made as a result of executing a block of code will be animated together
withAnimation(.linear(duration: 2)) {
// do something that will cause ViewModifier/Shape arguments to change somewhere
}
- explicit animation does not implicit animations!
Transitions
-
transform specify how to animate the arrival/departure of Views
-
Only works for Views that are inside CTAAOS(Containers That ARe Already On-Screen
-
Under the covers, a transition is nothing more than a pair of ViewModifiers. One of the modifiers is the "before" modification of teh View that's on the move. The other modifier is the "after" modification od the View that's on the move. Thus, a transition is just a version of a "changes in arguments to ViewModifiers" animation.
-
An asymmetric transition has 2 pairs of ViewModifiers
Animation
- the animation system takes the duration the animation is happening over and they're dividing it up into little pieces depending on what the curve is...chop it up into little pieces
- then a shape or the view modifier let's the system know what information inside it needs to be animated...it has to let the animate system know..
- then during animation, the animation system just calls them back and says plz draq urself with this start angle, and now with this start angle and on and on, moving the angle and asking to redraw itself repeatedly: regenerate ur body content with this aniamted value of ur piece of information
how do shape and viewmodifiers communicate with the animation system? Through this one var animatableData!
- var animatableData: Type
- must implement the protocol VectorArithemetic : b/c whataever this animatable data is, it's the thing that the animation system is going to chop up into little pieces and hand back to the shape or the ViewModifier thru the whole animation process
Shape and ViewModifier Animation
-
because it's communicationg both ways, this animatableData is a read-write var.
-
the setting of this var is the animation system telling the Shape/VM which 'piece' to draw : draw this draw that..
-
the getting of this var is the animation system getting the start/end points of an animation : when u set an argument it's gonna change that animatable data probably...
-
it's usally computed var..!
Reasons why font needs to be fixed
Author And Source
이 문제에 관하여(Lecture 7: ViewModifier Animation), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@sunnysideup/Lecture7-ViewModifier-Animation저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)