[SwiftUI] Path 에 따라 View 움직이기

positiontrimmedPath , currentPoint 를 이용해보자

naljin
6 min readSep 13, 2022

Preview

들어가기 전에

아래 UI 를 만들 일이 있다

왜인지는.. ^^..

튼 일단 Bezier path 를 이용해서 곡선 먼저 조져야할 것 같다

아래 사이트에서 대충 startPoint, endPoint, controlPoint 들을 어떻게 잡아야 저 형태랑 비슷하게 나올지 각을 보자

왼쪽 / 오른쪽

흠.. ㅇㅋㅇㅋ addCurve(to:, control1, control2) 이용해서 대충 이어 그렸다

var body: some View {
samplePath.stroke(style: StrokeStyle(lineWidth: 3))
}

오키 잘나온다

이제 이 Path 를 따라 다른 View(여기서는 🌕) 를 얹어서 이동시키고 싶단 말이지,,?

흠냐 어케 할까?

Path 를 따라 다른 View 얹기

아래처럼 positiontrimmedPath , currentPoint 를 이용해봤따

이게 뭔지는 하나씩 살펴보자

position(x:y:)

position(x:y:) modifier 를 통해 부모 뷰의 특정 좌표에 뷰의 center 를 배치할 수 있다

Positions the center of this view at the specified coordinates in its parent’s coordinate space.

코드와 결과를 보면 대충 감이 올지두?

Text("Hello, world!")
.background(.red)
.position(x: 100, y: 100)
.background(.blue)

참고로 view 를 positioning 하는 방법으로 offset() modifier 도 있다. 얘는 underlying geometry 를 실제로 변경하지 않고, 뷰가 렌더링되어야 하는 위치를 변경한다.

Text("Hello, world!")
.background(.red)
.offset(x: 100, y: 100)
.background(.blue)

positionoffset 에 대한 더 자세한 내용은 [SwiftUI] offset 과 position 의 layout 단계를 참고하자.

ㅇㅋ 그럼 요 안에 들어갈 x, y 좌표는 어떻게 구하냐?

이때 PathtrimmedPathcurrentPoint 이용할거다

trimmedPath(from:, to:)

fromto 사이값에 해당하는 Path 의 일부분을 얻을 수 있다 (fromto 에는 0 ~ 1 사이의 값이 들어감)

아까 만든 samplePath 에서 0 ~ 0.7 까지 잘라보면 아래처럼 나온다.

samplePath
.trimmedPath(from: 0, to: 0.7)
.stroke(style: StrokeStyle(lineWidth: 3))

currentPoint

Path 의 last point 에 접근할 수 있다 (만약 path 가 points 를 포함하고 있지 않다면 nil 반환).

그래서 아래 코드는 samplePath 의 0.5 위치에 해당하는 값을 나타낸다.

samplePath
.trimmedPath(from: 0, to: 0.5)
.currentPoint

이제 앞서 설명한 position , trimmedPath , currentPoint 를 다 합친 코드를 다시 보면?

현재의 내가 이해했으니까 미래의 나도 여기까지 보면 이해하겠지 머 ㅋㅎ 안되면 다시 정독해라 미래의 나야

Slider 로 값을 바꿔보면서도 위치를 확인해보자

잘 된다

위에서 간단한 설명을 위해 냅다 Path 를 만들어서 사용했다. 근데 Path절대 경로 안에서 좌표값에 맞춰 도형을 그린다는 사실이 맘에 안든다. 나는 상대 경로 받아서 그리고 싶은걸?

이를 위해 Shape 를 사용해야할 것 같다. Shapepath(in:)에서 주어진 Rect를 기반으로 상대 경로를 받아서 도형을 그린다 (해당 메서드 호출이 끝나야 최종적인 사이즈를 알 수 있음).

따라서 Shape를 이용하는 방식으로 한단계만 더 나아가 잘 조지면 아래와 같이 사용할 수 있다

최종 코드

굿

참고

--

--

Responses (1)