Skip to content

Instantly share code, notes, and snippets.

@mecid
Last active December 27, 2023 21:43
Show Gist options
  • Save mecid/18a80b18cc9670eef1d8667cf8c886bd to your computer and use it in GitHub Desktop.
Save mecid/18a80b18cc9670eef1d8667cf8c886bd to your computer and use it in GitHub Desktop.
High-performance Animatable Vector for SwiftUI
import SwiftUI
import enum Accelerate.vDSP
struct AnimatableVector: VectorArithmetic {
static var zero = AnimatableVector(values: [0.0])
static func + (lhs: AnimatableVector, rhs: AnimatableVector) -> AnimatableVector {
let count = min(lhs.values.count, rhs.values.count)
return AnimatableVector(values: vDSP.add(lhs.values[0..<count], rhs.values[0..<count]))
}
static func += (lhs: inout AnimatableVector, rhs: AnimatableVector) {
let count = min(lhs.values.count, rhs.values.count)
vDSP.add(lhs.values[0..<count], rhs.values[0..<count], result: &lhs.values[0..<count])
}
static func - (lhs: AnimatableVector, rhs: AnimatableVector) -> AnimatableVector {
let count = min(lhs.values.count, rhs.values.count)
return AnimatableVector(values: vDSP.subtract(lhs.values[0..<count], rhs.values[0..<count]))
}
static func -= (lhs: inout AnimatableVector, rhs: AnimatableVector) {
let count = min(lhs.values.count, rhs.values.count)
vDSP.subtract(lhs.values[0..<count], rhs.values[0..<count], result: &lhs.values[0..<count])
}
var values: [Double]
mutating func scale(by rhs: Double) {
vDSP.multiply(rhs, values, result: &values)
}
var magnitudeSquared: Double {
vDSP.sum(vDSP.multiply(values, values))
}
}
@joebez
Copy link

joebez commented Jun 9, 2023

I just noticed that the AnimatableVector code in the swiftwithmajid.com article includes this code:

mutating func scale(by rhs: Double) {
        values = vDSP.multiply(rhs, values)
}

while this gist makes a small change:

mutating func scale(by rhs: Double) {
        vDSP.multiply(rhs, values, result: &values)
}

However, even when using the code from the gist, the animation issue with the .spring() animation that I described above remains. 🤷‍♂️

@nyccoder
Copy link

nyccoder commented Jul 15, 2023

I has same situation with .spring() animation. Spending whole day with this. Tks to ur comment. Now know why.

I solved this more delicately.

I reinitiated "static var zero" in AnimatableVector before I initiate the View's vector property.

AnimatableVector.zero = AnimatableVector(values: [0.0, 0.0, 0.0, 0.0])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment