코어애니메이션 시작하기

코어 애니메이션은 뷰의 콘텐츠의 기하학적 특성등을 이동, 확대/축소, 회전 등을 결합하여 변형하며 애니메이팅하는데 적합하다.

아래와 같이 궤도를 도는 원의 주위를 도는 더 작은 원과, 다시 그 작은 원 주위를 도는 가장 작은 원의 움직임을 코어 애니메이션으로 묘사해보자. 이 때 그려지는 이미지는 CAShapeLayer를 사용해서 패스를 통해 그릴 수도 있겠지만, 간단한 원이기 때문에 레이어의 모서리를 둥글려서 표현할 것이다.

그려지는 모든 궤도는 테두리로 그려지는 원과 원 위의 작은 원으로 구성된다. 그러한 궤도를 CALayer로 만들어주는 함수 orbit(with: color:)를 다음과 같이 작성할 수 있다. 기본적으로 궤도를 표현하는 레이어가 있고, 다시 궤도 위의 위성을 표현하는 레이어를 만든 다음, 위성 레이어를 궤도 레이어에 서브 레이어로 추가해주면 된다.

func orbit(with diameter: CGFloat, color: NSColor) -> CALayer {
    // 궤도를 표현하는 원
    let _orbit = CALayer()
    _orbit.bounds = CGRect(x: 0, y: 0, width: diameter, height: diameter)
    _orbit.cornerRadius = diameter / 2
    _orbit.borderColor = color.cgColor
    _orbit.borderWidth = 1.5
    // 궤도 상의 위성을 표현하는 원
    let planet = CALayer()
    let r = diameter / 10
    planet.bounds = CGRect(x: 0, y: 0, width: r, height: r)
    planet.borderWidth = 1.5
    planet.cornerRadius = r/2
    planet.backgroundColor = color.cgColor
    planet.borderColor = color.cgColor
    planet.borderWidth = 1.5
    planet.borderColor = color.cgColor
    // 상위 레이어의 원점을 기준으로
    // 6시 방향에 위치하도록
    // X는 중간, Y는 0
    planet.position = CGPoint(x: diameter/2, y: 0)
    _orbit.addSublayer(planet)
    return _orbit
}

다음 코드는 애니메이션 객체를 만든다. 무한 회전을 반복하면 되며, 이 때 변할 수 있는 값은 회전속도 즉, 지속시간이다 한 바퀴 도는데 얼마나 걸리는지를 정해서 넘겨주면 그에 맞는 애니메이션을 생성하는 함수 animation(with:) 를 다음과 같이 작성할 수 있다.

회전하는 애니메이션은 CABasicAnimation으로 만들어지는데, 애니메이션이 추가될 레이어의 transform.rotation 키패스의 속성값을 조작하게 될 것이다.

참고로 회전하는 동작 자체에는 가속이나 감속이 적용되지 않을 예정이므로 애니메이션의 타이밍 함수를 선형으로 지정해줄 필요가 있다.

func animation(with duration: Double) -> CABasicAnimation {
    let anim = CABasicAnimation(keyPath: "transform.rotation")
    anim.timingFunction = CAMediaTimingFunction(name: .linear)
    anim.fromValue = 0
    anim.toValue = 2 * Double.pi // 2pi = 360'
    anim.duration = duration
    anim.repeatCount = HUGE
    return anim
}

이제 회전하는 레이어를 만드는 것은 간단하다. 레이어의 add(_:forKey:) 메소드를 호출하여 애니메이션을 추가한다. 이 때의 키는 애니메이션을 구분하기 위한 용도이며, 레이어의 특정한 키패스를 가리키는 항목이 아니다.

이제 세 개의 궤도를 만들고 각각을 연결한 후 애니메이션을 달아보자.

class ViewController: NSViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.wantsLayer = true
        view.layer?.backgroundColor = NSColor.white.cgColor
        let orbit1 = orbit(with: 200, color: .red)
        let orbit2 = orbit(with:120, color: .blue)
        let orbit3 = orbit(with:30, color: .green)
        orbit1.position = CGPoint(x:view.frame.midX, y: view.frame.midY)
        orbit2.position = CGPoint(x: 100, y:0)
        orbit3.position = CGPoint(x: 60, y: 0)
        orbit2.addSublayer(orbit3)
        orbit1.addSublayer(orbit2)
        orbit1.add(animation(with: 5.0), forKey: "orbit1")
        orbit2.add(animation(with: 3.5), forKey: "orbit2")
        orbit3.add(animation(with: 1.1), forKey: "orbit3")
        view.layer?.addSublayer(orbit1)
    }
}

Read more

워드프레스에서 고스트로 이전

워드프레스에서 고스트로 이전

이 글을 쓰면서도 믿기 힘든 사실인데, 블로그라는 걸 처음 시작한지가 20년이 되었습니다. 이글루스에서 처음 시작했다가, SK컴즈가 인수한다고 발표함과 동시에 워드프레스로 플랫폼을 옮겼죠. 워드프레스오 옮긴 이후에는 호스팅 환경을 이리 저리 옮기긴 했지만 거의 18년 가까이 워드프레스를 사용해온 것 같습니다. 그 동안 워드프레스는 블로깅 툴에서 명실상부한 범용CMS로 발전했습니다. 사실 웬만한 홈페이지들은 이제

By sooop
띄어쓰기에 대한 생각

띄어쓰기에 대한 생각

업무 메일을 쓸 때 가장 많이 쓰는 말 중에 하나가 메일 말미에 ‘업무에 참고 부탁 드립니다.‘인데요, 어느 날부터 아웃룩에서 이 ‘부탁 드립니다’가 틀렸다고 맞춤법 지적을 하기 시작했습니다. 맞는 말은 ‘부탁드립니다’라고 붙여 쓰는 거라고. 사실 아래아한글 시절부터 이전의 MS워드까지, 워드프로세서들의 한국어 맞춤법 검사 실력은 거의 있으나 마나 한

By sooop

구글 포토에서 아이클라우드로 탈출한 후기

한 때 구글 포토가 백업 용량을 무제한으로 제공해 주겠다고해서, 구글 포토를 사용해서 사진을 백업해왔습니다. 물론 이 이야기의 결말은 저나 이 글을 읽고 있는 여러분이나 모두 알고 있습니다. 사실 AI에게 학습 시킬 이미지 데이터를 모으기 위한 것일 뿐이라거나 하는 이야기는 그 당시에도 있었습니다만, 에이 그래도 구글인데 용량은 넉넉하게 주겠지…하는 순진한

By sooop

Julia의 함수 사용팁

연산자의 함수적 표기 Julia의 연산자는 기본적으로 함수이며, 함수 호출 표기와 같은 방식으로 호출하는 것이 가능합니다. 또한 그 자체로 함수이기 때문에 filter(), map() 과 같이 함수를 인자로 받는 함수에도 연산자를 그대로 적용하는 것이 가능합니다. 특히 + 연산자는 sum() 함수와 같이 여러 인자를 받아 인자들의 합을 구할 수 있습니다. 2 + 3 # = 5 +(2,

By sooop