Created
October 11, 2023 17:13
-
-
Save delasign/26196720ab9631f5083752434911dd6f to your computer and use it in GitHub Desktop.
Sample MetalUIView+Animations.swift for animating Metal drawings with a CADisplayLink
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// MetalUIView+Animations.swift | |
// Starter Project | |
// | |
// Created by Oscar de la Hera Gomez on 10/11/23. | |
// | |
import Foundation | |
import UIKit | |
extension MetalUIView { | |
func setupCADisplayLink() { | |
displayLink = CADisplayLink(target: self, selector: #selector(self.updateAnimationVariables)) | |
// Start the display link | |
displayLink.add(to: .main, forMode: .default) | |
// Determine the refresh rate | |
// Determine if the frame rate exists and if it is not 0 | |
// When this value is 0, the preferred frame rate is equal to the maximum refresh rate of the display, as indicated by the maximumFramesPerSecond property. | |
if let frameRate = displayLink.preferredFrameRateRange.preferred, frameRate != 0.0 { | |
displayLinkRefreshRate = CGFloat(1/frameRate) | |
debugPrint("\(MetalUIView.identifier) setupCADisplayLink \(DebuggingIdentifiers.actionOrEventSucceded) Refresh rate is \(frameRate) frames per second. This is the displayLink preferred FPS.") | |
} else { | |
let frameRate = UIScreen.main.maximumFramesPerSecond | |
displayLinkRefreshRate = CGFloat(1/frameRate) | |
debugPrint("\(MetalUIView.identifier) setupCADisplayLink \(DebuggingIdentifiers.actionOrEventSucceded) Refresh rate is \(frameRate) frames per second. This matches the screen") | |
} | |
debugPrint("\(MetalUIView.identifier) setupCADisplayLink \(DebuggingIdentifiers.actionOrEventSucceded) Setup Complete.") | |
} | |
@objc private func updateAnimationVariables() { | |
// Update the magnitude and direction | |
if magnitudeIsGrowing { | |
magnitude += displayLinkRefreshRate | |
} else { | |
magnitude -= displayLinkRefreshRate | |
} | |
if magnitude >= 1 { | |
magnitude = 1 | |
magnitudeIsGrowing = false | |
} else if magnitude <= 0 { | |
magnitude = 0 | |
magnitudeIsGrowing = true | |
} | |
// determine the new origin | |
let screenBounds = getCurrentScreenBounds() | |
let initialOrigin: CGPoint = CGPoint(x: screenBounds.midX, y: screenBounds.midY) | |
// The origin should only ever move 100 pixels north of the initial origin | |
let yOffsetMaximum: CGFloat = -100 | |
self.origin = CGPoint( | |
x: initialOrigin.x, | |
y: initialOrigin.y + yOffsetMaximum * magnitude | |
) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment