iOS 카메라 개발기 - 기본 카메라 UI를 픽셀로 재다
애플 기본 카메라의 줌 다이얼을 따라 그리려고 스크린샷을 극좌표로 펼치고 밝기 단면을 쟀다. 눈으로 '잘렸다'고 본 것은 그라데이션이었다.
egg2분 읽기
카메라 앱을 만들면 기본 카메라와 비교를 피할 수 없다. 사용자 손은 이미 기본 카메라에 익어 있어서 줌 다이얼이 조금만 달라도 어색하다.
그래서 지난 편의 줌 다이얼을 기본 카메라에 맞추기로 했다. 애플은 치수를 공개하지 않으니 스크린샷을 재는 수밖에 없었다. 기기는 iPhone 17 Pro, iOS 26.6.1.
다이얼을 극좌표로 펼쳤다
라벨의 x좌표를 읽어서 눈금 간격을 역산하는 방법도 있는데 원 위에 놓인 걸 직교 좌표로 읽는 셈이라 정밀하지 않다.
그래서 펼쳤다. 스크린샷에서 다이얼의 원을 피팅하고 각도 × 반지름으로 펼쳐 띠 모양의 이미지를 만든다. 그 위에서 밝기 단면을 재면 눈금이 직선 위에 늘어선다.
알아낸 것은 이렇다.
- 눈금 축은 옥타브당(배율 두 배마다) 48pt로 균일하다
- 반지름은 240pt
- 두꺼운 눈금은 정수 배율 자리
- 포인터 주변이 파인 모양은 V자가 아니라 지수 곡선이다. 호를 따라 3.3pt마다 1/e로 줄어든다
- 다이얼 양 끝은 잘린 게 아니라 그라데이션이다
마지막 것은 처음에 틀렸다. 눈으로 보고 “끝이 잘려 있다”고 판단해서 그렇게 그렸는데 단면을 재보니 서서히 사라지고 있었다. 눈으로는 경계만 보이고 밝기가 줄어드는 건 안 보였던 것 같다.
캡슐 높이는 세로 가운데에서 잰다
줌 버튼 캡슐의 높이를 쟀더니 34pt가 나왔다. 그걸로 그렸다가 되돌리고 다시 재서 또 되돌렸다.
모서리 근처에서 재고 있었다. 둥근 모서리 쪽은 높이가 줄어드니까 당연히 작게 나온다. 세로 중앙선에서 재니 48pt였다. 두 번 되돌린 끝에야 알았다.
폰트 크기는 글리프 폭으로 역산한다
라벨 폰트도 공개된 값이 없다. SF Rounded인 건 모양으로 알 수 있는데 크기와 굵기는 재야 했다.
후보 크기와 굵기마다 같은 문자열의 폭을 계산해서 스크린샷의 잉크 폭과 맞췄다.
for size in stride(from: 14.0, through: 18.0, by: 0.5) {
let base = UIFont.systemFont(ofSize: size, weight: .semibold)
let font = UIFont(descriptor: base.fontDescriptor.withDesign(.rounded)!, size: size)
let w = (label as NSString).size(withAttributes: [.font: font]).width
print(size, w)
}
SF Rounded Semibold 16pt에서 소수점까지 맞았다. 높이로도 해봤는데 잉크 높이는 1pt 넘게 어긋나서 판별에 못 썼다.
progress >= 1은 오지 않았다
지수 곡선을 따라가는 값에 progress >= 1이 되면 끝내는 분기를 뒀더니 영원히 안 걸렸다. 지수 곡선은 1에 닿지 않는다.
let progress = 1 - exp(-t / tau)
if progress > 0.999 { finish() } // >= 1은 영원히 안 온다
다이얼을 잘라내는 순서에서도 한 번 걸렸다. .clipped()를 .scaleEffect보다 먼저 두면 잘린 단면이 같이 축소돼서 끝이 드러난다.
// bad case - 잘린 가장자리가 축소를 따라온다
dial.clipped().scaleEffect(s)
// good case - 넓게 그리고, 줄인 다음에 자른다
dial.scaleEffect(s).clipped()
결국 나란히 놓고 맞췄다
세이프 에어리어 기준 오프셋 같은 위치값은 계산으로 맞추려다 여러 번 어긋났다. 기본 카메라 스크린샷과 내 스크린샷을 나란히 놓고 조정하는 게 제일 빨랐다.
돌아보면 재서 얻은 값은 믿을 만했는데 계산으로 낸 값은 번번이 틀렸다.
겹쳐 그리는 두 요소는 좌표를 따로 계산하지 말고 같은 ZStack에 넣어 원점을 공유시킨다. 이때 .overlay는 부모 레이아웃 크기에 영향을 주지 않고 opacity(0)은 크기를 그대로 차지한다는 걸 알아두면 덜 헤맨다.
다이얼 하나 따라 그리는 데 이 정도로 잴 줄은 몰랐다. 애플이 치수를 공개해줬으면 이 편은 없었을 거다.
다음 편은 화면 밖 이야기다. 잠금 화면과 제어센터에서 카메라를 켜는 법.
Filed under 개발