Irbisa · Шпаргалка
Анимации и Core Animation
CALayer, неявные анимации, UIViewPropertyAnimator, переходы, PhaseAnimator, KeyframeAnimator
Эта точка уезжает в x = 300 и остаётся там. Что выведет
printчерез секунду, и почему перенос в 100 ничего не меняет на экране?let dot = ballView.layer // ballView is centred at x = 40 let slide = CABasicAnimation(keyPath: "position.x")slide.fromValue = 40slide.toValue = 300slide.duration = 0.5slide.fillMode = .forwardsslide.isRemovedOnCompletion = falsedot.add(slide, forKey: "slide") DispatchQueue.main.asyncAfter(deadline: .now() + 1) { print(dot.position.x) dot.position.x = 100 // nothing moves on screen}Почему изменение свойства у отдельного
CALayerанимируется само, а то же изменение у слоя, на котором стоит вью, просто прыгает?// A standalone layer: no delegate, so the default 0.25 s action runslet badge = CALayer() // added to view.layer in an earlier run-loop turn, already on screenbadge.opacity = 0 // fades out on its own over 0.25 s // A view's backing layer: the view answers NSNull outside an animation blockview.layer.opacity = 0 // snaps…Что такое
CATransaction, и как запретить анимацию для одного изменения слоя?// No animation for this change: the action search never runsCATransaction.begin()CATransaction.setDisableActions(true)gradient.frame = boundsCATransaction.commit()…Где будет нарисована карточка с трансформом
aи с трансформомb, и что каждый раз выведетprint?// card is 100 x 100, centred at (200, 200), with an identity transformlet a = CGAffineTransform(translationX: 100, y: 0).rotated(by: .pi / 2)let b = CGAffineTransform(rotationAngle: .pi / 2).translatedBy(x: 100, y: 0) card.transform = aprint(card.center) // what prints, and where is the card drawn? card.transform = bprint(card.center) // and now?Какие подклассы
CALayerвы используете, и почему анимированное кольцо прогресса лучше делать наCAShapeLayer, а не черезdraw(_:)?// draw(_:) version: 300 x 300 pt at 3x = 900 x 900 px x 4 B, about 3.2 MB, repainted per change // Shape layer version: no bitmap, and progress is one animatable propertylet ring = CAShapeLayer()ring.frame = CGRect(x: 0, y: 0, width: 300, height: 300)ring.path = UIBezierPath(ovalIn: ring.bounds.insetBy(dx: 4, dy: 4)).cgPath…Что такое
CADisplayLink, когда он нужен вместо Core Animation, и как получить от него 120 Гц на iPhone с ProMotion?final class WaveformView: UIView { private var link: CADisplayLink? private var startTime: CFTimeInterval = 0 private var phase: Double = 0 override func didMoveToWindow() {…Что даёт
UIViewPropertyAnimatorпо сравнению сUIView.animate, и как управлять им из pan-жеста?final class SheetController: UIViewController { let sheet = UIView() private var animator: UIViewPropertyAnimator? @objc func handlePan(_ pan: UIPanGestureRecognizer) { let travel = sheet.bounds.height…Найдите баг: по нажатию на Filters панель должна плавно выезжать, но она сразу прыгает на полную высоту без анимации.
final class FiltersViewController: UIViewController { let panel = UIView() private var panelHeight: NSLayoutConstraint! // panel.heightAnchor, starts at 0 private var isExpanded = false @objc func toggleFilters() { isExpanded.toggle() UIView.animate(withDuration: 0.3) { self.panelHeight.constant = self.isExpanded ? 320 : 0 } }}Как реализовать кастомный переход между view controller, и кто добавляет и убирает вью в контейнере?
final class SlideAnimator: NSObject, UIViewControllerAnimatedTransitioning { let operation: UINavigationController.Operation init(operation: UINavigationController.Operation) { self.operation = operation } func transitionDuration(using context: UIViewControllerContextTransitioning?) -> TimeInterval { 0.32 }…Когда в SwiftUI на самом деле срабатывает
.transition, и почему вью иногда просто появляется без него?struct Inbox: View { @State private var showBanner = false @State private var items = Message.samples var body: some View { VStack {…Как выполнить код, когда анимация в SwiftUI закончилась, и как запустить одну анимацию после другой?
struct SavedToast: View { @State private var visible = false @State private var offset: CGFloat = 0 let onFinished: () -> Void var body: some View {…Чем
phaseAnimatorотличается отkeyframeAnimator, и когда достаточно анимации сrepeatForever?struct Pose { var scale = 1.0, angle = Angle.zero, lift = 0.0 } struct BellBadge: View { @State private var taps = 0 var body: some View {…Этот
Ringперескакивает к новому прогрессу вместо анимации: почему, и при чём здесьAnimatableиanimatableData?struct Ring: Shape { var progress: Double // 0...1 func path(in rect: CGRect) -> Path { var path = Path() path.addArc(center: CGPoint(x: rect.midX, y: rect.midY), radius: rect.width / 2, startAngle: .degrees(-90), endAngle: .degrees(-90 + 360 * progress), clockwise: false) return path }} // Ring(progress: done).stroke(.teal, lineWidth: 8)// .animation(.easeOut(duration: 0.6), value: done)Чем неявные анимации Core Animation отличаются от явных, и что такое
CABasicAnimation,CAKeyframeAnimationиCAAnimationGroup?// Basic: one key path, from one value to anotherlet fade = CABasicAnimation(keyPath: "opacity")fade.fromValue = 1.0fade.toValue = 0.3fade.duration = 0.3badge.opacity = 0.3 // the model value is yours to set…Чем model layer отличается от presentation layer, и почему по вью нельзя тапнуть, пока она анимируется?
final class GameViewController: UIViewController { let ball = UIView(frame: CGRect(x: 20, y: 200, width: 44, height: 44)) func launch() { UIView.animate(withDuration: 2) { self.ball.center.x = 320 } print(ball.center.x) // 320: the model is already there…Как работает
matchedGeometryEffect, и почему карточка, которая должна разворачиваться в экран деталей, вместо этого просто гаснет и прыгает?struct CardGallery: View { @Namespace private var cards // must outlive both sides of the pair @State private var expanded: Int? var body: some View { ZStack {…Как передать скорость жеста в момент отпускания в пружинную анимацию, и что означают
durationиbounceу пружины?// UIKit: the release keeps the throwfunc endDrag(_ pan: UIPanGestureRecognizer) { let target = shouldDismiss ? view.bounds.maxY + sheet.bounds.height / 2 : restingY let distance = target - sheet.center.y // initialVelocity is in "remaining distances per second", not points per second let relative = abs(distance) < 1 ? 0 : pan.velocity(in: view).y / distance…Как сделать кастомный переход интерактивным, и что должно произойти, если пользователь отменил его на полпути?
final class DismissInteraction: UIPercentDrivenInteractiveTransition { private(set) var isDriving = false weak var presented: UIViewController? @objc func handle(_ pan: UIPanGestureRecognizer) { let progress = min(max(pan.translation(in: pan.view).y / 300, 0), 1)…Какие свойства слоя дёшево анимировать, и что заставляет render server переходить на offscreen rendering?
Если анимация дёргается на реальном iPhone, как понять, кто опаздывает: commit вашего приложения или render server?